diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 65bbd26..e7b38a0 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -104,6 +104,8 @@ cpuidle/
 	- info on CPU_IDLE, CPU idle state management subsystem.
 cputopology.txt
 	- documentation on how CPU topology info is exported via sysfs.
+crc32.txt
+	- brief tutorial on CRC computation
 cris/
 	- directory with info about Linux on CRIS architecture.
 crypto/
diff --git a/Documentation/ABI/testing/debugfs-olpc b/Documentation/ABI/testing/debugfs-olpc
new file mode 100644
index 0000000..49b9a4e
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-olpc
@@ -0,0 +1,16 @@
+What:		/sys/kernel/debug/olpc-ec/generic
+Date:		Dec 2011
+KernelVersion:	3.3
+Contact:	devel@lists.laptop.org
+Description:
+
+A generic interface for executing OLPC Embedded Controller commands and
+reading their responses.
+
+To execute a command, write data with the format: CC:N A A A A
+CC is the (hex) command, N is the count of expected reply bytes, and A A A A
+are optional (hex) arguments.
+
+To read the response (if any), read from the generic node after executing
+a command. Hex reply bytes will be returned, *whether or not* they came from
+the immediately previous command.
diff --git a/Documentation/ABI/testing/sysfs-bus-rpmsg b/Documentation/ABI/testing/sysfs-bus-rpmsg
new file mode 100644
index 0000000..189e419
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-rpmsg
@@ -0,0 +1,75 @@
+What:		/sys/bus/rpmsg/devices/.../name
+Date:		June 2011
+KernelVersion:	3.3
+Contact:	Ohad Ben-Cohen <ohad@wizery.com>
+Description:
+		Every rpmsg device is a communication channel with a remote
+		processor. Channels are identified with a (textual) name,
+		which is maximum 32 bytes long (defined as RPMSG_NAME_SIZE in
+		rpmsg.h).
+
+		This sysfs entry contains the name of this channel.
+
+What:		/sys/bus/rpmsg/devices/.../src
+Date:		June 2011
+KernelVersion:	3.3
+Contact:	Ohad Ben-Cohen <ohad@wizery.com>
+Description:
+		Every rpmsg device is a communication channel with a remote
+		processor. Channels have a local ("source") rpmsg address,
+		and remote ("destination") rpmsg address. When an entity
+		starts listening on one end of a channel, it assigns it with
+		a unique rpmsg address (a 32 bits integer). This way when
+		inbound messages arrive to this address, the rpmsg core
+		dispatches them to the listening entity (a kernel driver).
+
+		This sysfs entry contains the src (local) rpmsg address
+		of this channel. If it contains 0xffffffff, then an address
+		wasn't assigned (can happen if no driver exists for this
+		channel).
+
+What:		/sys/bus/rpmsg/devices/.../dst
+Date:		June 2011
+KernelVersion:	3.3
+Contact:	Ohad Ben-Cohen <ohad@wizery.com>
+Description:
+		Every rpmsg device is a communication channel with a remote
+		processor. Channels have a local ("source") rpmsg address,
+		and remote ("destination") rpmsg address. When an entity
+		starts listening on one end of a channel, it assigns it with
+		a unique rpmsg address (a 32 bits integer). This way when
+		inbound messages arrive to this address, the rpmsg core
+		dispatches them to the listening entity.
+
+		This sysfs entry contains the dst (remote) rpmsg address
+		of this channel. If it contains 0xffffffff, then an address
+		wasn't assigned (can happen if the kernel driver that
+		is attached to this channel is exposing a service to the
+		remote processor. This make it a local rpmsg server,
+		and it is listening for inbound messages that may be sent
+		from any remote rpmsg client; it is not bound to a single
+		remote entity).
+
+What:		/sys/bus/rpmsg/devices/.../announce
+Date:		June 2011
+KernelVersion:	3.3
+Contact:	Ohad Ben-Cohen <ohad@wizery.com>
+Description:
+		Every rpmsg device is a communication channel with a remote
+		processor. Channels are identified by a textual name (see
+		/sys/bus/rpmsg/devices/.../name above) and have a local
+		("source") rpmsg address, and remote ("destination") rpmsg
+		address.
+
+		A channel is first created when an entity, whether local
+		or remote, starts listening on it for messages (and is thus
+		called an rpmsg server).
+
+		When that happens, a "name service" announcement is sent
+		to the other processor, in order to let it know about the
+		creation of the channel (this way remote clients know they
+		can start sending messages).
+
+		This sysfs entry tells us whether the channel is a local
+		server channel that is announced (values are either
+		true or false).
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index b638e50..5f70f73 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -437,4 +437,21 @@ X!Idrivers/video/console/fonts.c
 !Edrivers/i2c/i2c-core.c
   </chapter>
 
+  <chapter id="hsi">
+     <title>High Speed Synchronous Serial Interface (HSI)</title>
+
+     <para>
+	High Speed Synchronous Serial Interface (HSI) is a
+	serial interface mainly used for connecting application
+	engines (APE) with cellular modem engines (CMT) in cellular
+	handsets.
+
+	HSI provides multiplexing for up to 16 logical channels,
+	low-latency and full duplex communication.
+     </para>
+
+!Iinclude/linux/hsi/hsi.h
+!Edrivers/hsi/hsi.c
+  </chapter>
+
 </book>
diff --git a/Documentation/RCU/RTFP.txt b/Documentation/RCU/RTFP.txt
index c43460d..fc179c8 100644
--- a/Documentation/RCU/RTFP.txt
+++ b/Documentation/RCU/RTFP.txt
@@ -1,9 +1,10 @@
-Read the F-ing Papers!
+Read the Fscking Papers!
 
 
 This document describes RCU-related publications, and is followed by
 the corresponding bibtex entries.  A number of the publications may
-be found at http://www.rdrop.com/users/paulmck/RCU/.
+be found at http://www.rdrop.com/users/paulmck/RCU/.  For others, browsers
+and search engines will usually find what you are looking for.
 
 The first thing resembling RCU was published in 1980, when Kung and Lehman
 [Kung80] recommended use of a garbage collector to defer destruction
@@ -160,7 +161,25 @@ which Mathieu Desnoyers is now maintaining [MathieuDesnoyers2009URCU]
 [MathieuDesnoyersPhD].  TINY_RCU [PaulEMcKenney2009BloatWatchRCU] made
 its appearance, as did expedited RCU [PaulEMcKenney2009expeditedRCU].
 The problem of resizeable RCU-protected hash tables may now be on a path
-to a solution [JoshTriplett2009RPHash].
+to a solution [JoshTriplett2009RPHash].  A few academic researchers are now
+using RCU to solve their parallel problems [HariKannan2009DynamicAnalysisRCU].
+
+2010 produced a simpler preemptible-RCU implementation based on TREE_RCU
+[PaulEMcKenney2010SimpleOptRCU], lockdep-RCU [PaulEMcKenney2010LockdepRCU],
+another resizeable RCU-protected hash table [HerbertXu2010RCUResizeHash]
+(this one consuming more memory, but allowing arbitrary changes in hash
+function, as required for DoS avoidance in the networking code), realization
+of the 2009 resizeable hash table [JoshTriplett2010RPHash], an update on the
+RCU API [PaulEMcKenney2010RCUAPI].
+
+2011 marked the inclusion of Nick Piggin's fully lockless dentry search
+[LinusTorvalds2011Linux2:6:38:rc1:NPigginVFS], an RCU-protected red-black
+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].
+
 
 Bibtex Entries
 
@@ -173,6 +192,14 @@ 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.
+}
 }
 
 @techreport{Manber82
@@ -184,6 +211,31 @@ Bibtex Entries
 ,number="82-01-01"
 ,month="January"
 ,pages="28"
+,annotation={
+	.
+	Superseded by Manber84.
+	.
+	Describes concurrent AVL tree implementation.  Uses a
+	garbage-collection mechanism to handle concurrent use and deletion
+	of nodes in the tree, but lacks the summary-of-execution-history
+	concept of read-copy locking.
+	.
+	Keeps full list of processes that were active when a given
+	node was to be deleted, and waits until all such processes have
+	-terminated- before allowing this node to be reused.  This is
+	not described in great detail -- one could imagine using process
+	IDs for this if the ID space was large enough that overlapping
+	never occurred.
+	.
+	This restriction makes this algorithm unsuitable for use in
+	systems comprised of long-lived processes.  It also produces
+	completely unacceptable overhead in systems with large numbers
+	of processes.  Finally, it is specific to AVL trees.
+	.
+	Cites Kung80, so not an independent invention, but the first
+	RCU-like usage that does not rely on an automatic garbage
+	collector.
+}
 }
 
 @article{Manber84
@@ -195,6 +247,74 @@ Bibtex Entries
 ,volume="9"
 ,number="3"
 ,pages="439-455"
+,annotation={
+	Describes concurrent AVL tree implementation.  Uses a
+	garbage-collection mechanism to handle concurrent use and deletion
+	of nodes in the tree, but lacks the summary-of-execution-history
+	concept of read-copy locking.
+	.
+	Keeps full list of processes that were active when a given
+	node was to be deleted, and waits until all such processes have
+	-terminated- before allowing this node to be reused.  This is
+	not described in great detail -- one could imagine using process
+	IDs for this if the ID space was large enough that overlapping
+	never occurred.
+	.
+	This restriction makes this algorithm unsuitable for use in
+	systems comprised of long-lived processes.  It also produces
+	completely unacceptable overhead in systems with large numbers
+	of processes.  Finally, it is specific to AVL trees.
+}
+}
+
+@Conference{RichardRashid87a
+,Author="Richard Rashid and Avadis Tevanian and Michael Young and
+David Golub and Robert Baron and David Black and William Bolosky and
+Jonathan Chew"
+,Title="Machine-Independent Virtual Memory Management for Paged
+Uniprocessor and Multiprocessor Architectures"
+,Booktitle="{2\textsuperscript{nd} Symposium on Architectural Support
+for Programming Languages and Operating Systems}"
+,Publisher="Association for Computing Machinery"
+,Month="October"
+,Year="1987"
+,pages="31-39"
+,Address="Palo Alto, CA"
+,note="Available:
+\url{http://www.cse.ucsc.edu/~randal/221/rashid-machvm.pdf}
+[Viewed February 17, 2005]"
+,annotation={
+	Describes lazy TLB flush, where one waits for each CPU to pass
+	through a scheduling-clock interrupt before reusing a given range
+	of virtual address.  Does not describe how one determines that
+	all CPUs have in fact taken such an interrupt, though there are
+	no shortage of straightforward methods for accomplishing this.
+	.
+	Note that it does not make sense to just wait a fixed amount of
+	time, since a given CPU might have interrupts disabled for an
+	extended amount of time.
+}
+}
+
+@article{BarbaraLiskov1988ArgusCACM
+,author = {Barbara Liskov}
+,title = {Distributed programming in {Argus}}
+,journal = {Commun. ACM}
+,volume = {31}
+,number = {3}
+,year = {1988}
+,issn = {0001-0782}
+,pages = {300--312}
+,doi = {http://doi.acm.org/10.1145/42392.42399}
+,publisher = {ACM}
+,address = {New York, NY, USA}
+,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
+	out of date."  Relies on semantics -- approximate numerical
+	values sometimes OK.
+}
 }
 
 @techreport{Hennessy89
@@ -216,6 +336,13 @@ Bibtex Entries
 ,year="1990"
 ,number="CS-TR-2222.1"
 ,month="June"
+,annotation={
+	Concurrent access to skip lists.  Has both weak and strong search.
+	Uses concept of ``garbage queue'', but has no real way of cleaning
+	the garbage efficiently.
+	.
+	Appears to be an independent invention of an RCU-like mechanism.
+}
 }
 
 @Book{Adams91
@@ -223,20 +350,15 @@ Bibtex Entries
 ,title="Concurrent Programming, Principles, and Practices"
 ,Publisher="Benjamin Cummins"
 ,Year="1991"
+,annotation={
+	Has a few paragraphs describing ``chaotic relaxation'', a
+	numerical analysis technique that allows multiprocessors to
+	avoid synchronization overhead by using possibly-stale data.
+	.
+	Seems like this is descended from yet another independent
+	invention of RCU-like function -- but this is restricted
+	in that reclamation is not necessary.
 }
-
-@phdthesis{HMassalinPhD
-,author="H. Massalin"
-,title="Synthesis: An Efficient Implementation of Fundamental Operating
-System Services"
-,school="Columbia University"
-,address="New York, NY"
-,year="1992"
-,annotation="
-	Mondo optimizing compiler.
-	Wait-free stuff.
-	Good advice: defer work to avoid synchronization.
-"
 }
 
 @unpublished{Jacobson93
@@ -244,7 +366,13 @@ System Services"
 ,title="Avoid Read-Side Locking Via Delayed Free"
 ,year="1993"
 ,month="September"
-,note="Verbal discussion"
+,note="private communication"
+,annotation={
+	Use fixed time delay to approximate grace period.  Very simple,
+	but subject to random memory corruption under heavy load.
+	.
+	Independent invention of RCU-like mechanism.
+}
 }
 
 @Conference{AjuJohn95
@@ -256,6 +384,17 @@ System Services"
 ,Year="1995"
 ,pages="11-23"
 ,Address="New Orleans, LA"
+,note="Available:
+\url{https://www.usenix.org/publications/library/proceedings/neworl/full_papers/john.a}
+[Viewed October 1, 2010]"
+,annotation={
+	Age vnodes out of the cache, and have a fixed time set by a kernel
+	parameter.  Not clear that all races were in fact correctly handled.
+	Used a 20-minute time by default, which would most definitely not
+	be suitable during DoS attacks or virus scans.
+	.
+	Apparently independent invention of RCU-like mechanism.
+}
 }
 
 @conference{Pu95a,
@@ -301,31 +440,47 @@ Utilizing Execution History and Thread Monitoring"
 ,institution="US Patent and Trademark Office"
 ,address="Washington, DC"
 ,year="1995"
-,number="US Patent 5,442,758 (contributed under GPL)"
+,number="US Patent 5,442,758"
 ,month="August"
+,annotation={
+	Describes the parallel RCU infrastructure.  Includes NUMA aspect
+	(structure of bitmap can reflect bus structure of computer system).
+	.
+	Another independent invention of an RCU-like mechanism, but the
+	"real" RCU this time!
+}
 }
 
 @techreport{Slingwine97
 ,author="John D. Slingwine and Paul E. McKenney"
-,title="Method for maintaining data coherency using thread
-activity summaries in a multicomputer system"
+,title="Method for Maintaining Data Coherency Using Thread Activity
+Summaries in a Multicomputer System"
 ,institution="US Patent and Trademark Office"
 ,address="Washington, DC"
 ,year="1997"
-,number="US Patent 5,608,893 (contributed under GPL)"
+,number="US Patent 5,608,893"
 ,month="March"
+,pages="19"
+,annotation={
+	Describes use of RCU to synchronize data between a pair of
+	SMP/NUMA computer systems.
+}
 }
 
 @techreport{Slingwine98
 ,author="John D. Slingwine and Paul E. McKenney"
-,title="Apparatus and method for achieving reduced overhead
-mutual exclusion and maintaining coherency in a multiprocessor
-system utilizing execution history and thread monitoring"
+,title="Apparatus and Method for Achieving Reduced Overhead Mutual
+Exclusion and Maintaining Coherency in a Multiprocessor System
+Utilizing Execution History and Thread Monitoring"
 ,institution="US Patent and Trademark Office"
 ,address="Washington, DC"
 ,year="1998"
-,number="US Patent 5,727,209 (contributed under GPL)"
+,number="US Patent 5,727,209"
 ,month="March"
+,annotation={
+	Describes doing an atomic update by copying the data item and
+	then substituting it into the data structure.
+}
 }
 
 @Conference{McKenney98
@@ -337,6 +492,15 @@ 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.
+}
 }
 
 @Conference{Gamsa99
@@ -349,18 +513,76 @@ 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).
+}
+}
+
+@unpublished{RustyRussell2000a
+,Author="Rusty Russell"
+,Title="Re: modular net drivers"
+,month="June"
+,year="2000"
+,day="23"
+,note="Available:
+\url{http://oss.sgi.com/projects/netdev/archive/2000-06/msg00250.html}
+[Viewed April 10, 2006]"
+,annotation={
+	Proto-RCU proposal from Phil Rumpf and Rusty Russell.
+	Yet another independent invention of RCU.
+	Outline of algorithm to unload modules...
+	.
+	Appeared on net-dev mailing list.
+}
+}
+
+@unpublished{RustyRussell2000b
+,Author="Rusty Russell"
+,Title="Re: modular net drivers"
+,month="June"
+,year="2000"
+,day="24"
+,note="Available:
+\url{http://oss.sgi.com/projects/netdev/archive/2000-06/msg00254.html}
+[Viewed April 10, 2006]"
+,annotation={
+	Proto-RCU proposal from Phil Rumpf and Rusty Russell.
+	.
+	Appeared on net-dev mailing list.
+}
+}
+
+@unpublished{McKenney01b
+,Author="Paul E. McKenney and Dipankar Sarma"
+,Title="Read-Copy Update Mutual Exclusion in {Linux}"
+,month="February"
+,year="2001"
+,note="Available:
+\url{http://lse.sourceforge.net/locking/rcu/rcupdate_doc.html}
+[Viewed October 18, 2004]"
+,annotation={
+	Prototypical Linux documentation for RCU.
+}
 }
 
 @techreport{Slingwine01
 ,author="John D. Slingwine and Paul E. McKenney"
-,title="Apparatus and method for achieving reduced overhead
-mutual exclusion and maintaining coherency in a multiprocessor
-system utilizing execution history and thread monitoring"
+,title="Apparatus and Method for Achieving Reduced Overhead Mutual
+Exclusion and Maintaining Coherency in a Multiprocessor System
+Utilizing Execution History and Thread Monitoring"
 ,institution="US Patent and Trademark Office"
 ,address="Washington, DC"
 ,year="2001"
-,number="US Patent 5,219,690 (contributed under GPL)"
+,number="US Patent 6,219,690"
 ,month="April"
+,annotation={
+	'Change in mode' aspect of RCU.  Can be thought of as a lazy barrier.
+}
 }
 
 @Conference{McKenney01a
@@ -372,14 +594,61 @@ Orran Krieger and Rusty Russell and Dipankar Sarma and Maneesh Soni"
 ,Year="2001"
 ,note="Available:
 \url{http://www.linuxsymposium.org/2001/abstracts/readcopy.php}
-\url{http://www.rdrop.com/users/paulmck/rclock/rclock_OLS.2001.05.01c.pdf}
+\url{http://www.rdrop.com/users/paulmck/RCU/rclock_OLS.2001.05.01c.pdf}
 [Viewed June 23, 2004]"
-annotation="
-Described RCU, and presented some patches implementing and using it in
-the Linux kernel.
+,annotation={
+	Described RCU, and presented some patches implementing and using
+	it in the Linux kernel.
+}
+}
+
+@unpublished{McKenney01f
+,Author="Paul E. McKenney"
+,Title="{RFC:} patch to allow lock-free traversal of lists with insertion"
+,month="October"
+,year="2001"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=100259266316456&w=2}
+[Viewed June 23, 2004]"
+,annotation="
+	Memory-barrier and Alpha thread.  100 messages, not too bad...
+"
+}
+
+@unpublished{Spraul01
+,Author="Manfred Spraul"
+,Title="Re: {RFC:} patch to allow lock-free traversal of lists with insertion"
+,month="October"
+,year="2001"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=100264675012867&w=2}
+[Viewed June 23, 2004]"
+,annotation="
+	Suggested burying memory barriers in Linux's list-manipulation
+	primitives.
 "
 }
 
+@unpublished{LinusTorvalds2001a
+,Author="Linus Torvalds"
+,Title="{Re:} {[Lse-tech]} {Re:} {RFC:} patch to allow lock-free traversal of lists with insertion"
+,month="October"
+,year="2001"
+,note="Available:
+\url{http://lkml.org/lkml/2001/10/13/105}
+[Viewed August 21, 2004]"
+}
+
+@unpublished{Blanchard02a
+,Author="Anton Blanchard"
+,Title="some RCU dcache and ratcache results"
+,month="March"
+,year="2002"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=101637107412972&w=2}
+[Viewed October 18, 2004]"
+}
+
 @Conference{Linder02a
 ,Author="Hanna Linder and Dipankar Sarma and Maneesh Soni"
 ,Title="Scalability of the Directory Entry Cache"
@@ -387,6 +656,10 @@ the Linux kernel.
 ,Month="June"
 ,Year="2002"
 ,pages="289-300"
+,annotation="
+	Measured scalability of Linux 2.4 kernel's directory-entry cache
+	(dcache), and measured some scalability enhancements.
+"
 }
 
 @Conference{McKenney02a
@@ -400,49 +673,76 @@ 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="
+	Presented and compared a number of RCU implementations for the
+	Linux kernel.
+"
 }
 
-@conference{Michael02a
-,author="Maged M. Michael"
-,title="Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic
-Reads and Writes"
-,Year="2002"
-,Month="August"
-,booktitle="{Proceedings of the 21\textsuperscript{st} Annual ACM
-Symposium on Principles of Distributed Computing}"
-,pages="21-30"
+@unpublished{Sarma02a
+,Author="Dipankar Sarma"
+,Title="specweb99: dcache scalability results"
+,month="July"
+,year="2002"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=102645767914212&w=2}
+[Viewed June 23, 2004]"
 ,annotation="
-	Each thread keeps an array of pointers to items that it is
-	currently referencing.	Sort of an inside-out garbage collection
-	mechanism, but one that requires the accessing code to explicitly
-	state its needs.  Also requires read-side memory barriers on
-	most architectures.
+	Compare fastwalk and RCU for dcache.  RCU won.
 "
 }
 
-@conference{Michael02b
-,author="Maged M. Michael"
-,title="High Performance Dynamic Lock-Free Hash Tables and List-Based Sets"
-,Year="2002"
-,Month="August"
-,booktitle="{Proceedings of the 14\textsuperscript{th} Annual ACM
-Symposium on Parallel
-Algorithms and Architecture}"
-,pages="73-82"
+@unpublished{Barbieri02
+,Author="Luca Barbieri"
+,Title="Re: {[PATCH]} Initial support for struct {vfs\_cred}"
+,month="August"
+,year="2002"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=103082050621241&w=2}
+[Viewed: June 23, 2004]"
 ,annotation="
-	Like the title says...
+	Suggested RCU for vfs\_shared\_cred.
 "
 }
 
-@InProceedings{HerlihyLM02
-,author={Maurice Herlihy and Victor Luchangco and Mark Moir}
-,title="The Repeat Offender Problem: A Mechanism for Supporting Dynamic-Sized,
-Lock-Free Data Structures"
-,booktitle={Proceedings of 16\textsuperscript{th} International
-Symposium on Distributed Computing}
-,year=2002
+@unpublished{Dickins02a
+,author="Hugh Dickins"
+,title="Use RCU for System-V IPC"
+,year="2002"
+,month="October"
+,note="private communication"
+}
+
+@unpublished{Sarma02b
+,Author="Dipankar Sarma"
+,Title="Some dcache\_rcu benchmark numbers"
 ,month="October"
-,pages="339-353"
+,year="2002"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=103462075416638&w=2}
+[Viewed June 23, 2004]"
+,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
+,Author="Linus Torvalds"
+,Title="Re: {[PATCH]} small fixes in brlock.h"
+,month="March"
+,year="2003"
+,note="Available:
+\url{http://lkml.org/lkml/2003/3/9/205}
+[Viewed March 13, 2006]"
+,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
@@ -457,6 +757,20 @@ B. Rosenburg and M. Stumm and J. Xenidis"
 ,volume="42"
 ,number="1"
 ,pages="60-76"
+,annotation="
+	Use of RCU to enable hot-swapping for autonomic behavior in K42.
+"
+}
+
+@unpublished{Seigh03
+,author="Joseph W. {Seigh II}"
+,title="Read Copy Update"
+,Year="2003"
+,Month="March"
+,note="email correspondence"
+,annotation="
+	Described the relationship of the VM/XA passive serialization to RCU.
+"
 }
 
 @Conference{Arcangeli03
@@ -470,6 +784,27 @@ 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="
+	Compared updated RCU implementations for the Linux kernel, and
+	described System V IPC use of RCU, including order-of-magnitude
+	performance improvements.
+"
+}
+
+@Conference{Soules03a
+,Author="Craig A. N. Soules and Jonathan Appavoo and Kevin Hui and
+Dilma {Da Silva} and Gregory R. Ganger and Orran Krieger and
+Michael Stumm and Robert W. Wisniewski and Marc Auslander and
+Michal Ostrowski and Bryan Rosenburg and Jimi Xenidis"
+,Title="System Support for Online Reconfiguration"
+,Booktitle="Proceedings of the 2003 USENIX Annual Technical Conference"
+,Publisher="USENIX Association"
+,year="2003"
+,month="June"
+,pages="141-154"
 }
 
 @article{McKenney03a
@@ -481,6 +816,22 @@ Dipankar Sarma"
 ,volume="1"
 ,number="114"
 ,pages="18-26"
+,note="Available:
+\url{http://www.linuxjournal.com/article/6993}
+[Viewed November 14, 2007]"
+,annotation="
+	Reader-friendly intro to RCU, with the infamous old-man-and-brat
+	cartoon.
+"
+}
+
+@unpublished{Sarma03a
+,Author="Dipankar Sarma"
+,Title="RCU low latency patches"
+,month="December"
+,year="2003"
+,note="Message ID: 20031222180114.GA2248@in.ibm.com"
+,annotation="dipankar/ct.2004.03.27/RCUll.2003.12.22.patch"
 }
 
 @techreport{Friedberg03a
@@ -489,9 +840,14 @@ Dipankar Sarma"
 ,institution="US Patent and Trademark Office"
 ,address="Washington, DC"
 ,year="2003"
-,number="US Patent 6,662,184 (contributed under GPL)"
+,number="US Patent 6,662,184"
 ,month="December"
 ,pages="112"
+,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
@@ -503,6 +859,12 @@ Dipankar Sarma"
 ,volume="1"
 ,number="118"
 ,pages="38-46"
+,note="Available:
+\url{http://www.linuxjournal.com/node/7124}
+[Viewed December 26, 2010]"
+,annotation="
+	Reader friendly intro to dcache and RCU.
+"
 }
 
 @Conference{McKenney04b
@@ -514,119 +876,519 @@ Dipankar Sarma"
 ,Address="Adelaide, Australia"
 ,note="Available:
 \url{http://www.linux.org.au/conf/2004/abstracts.html#90}
-\url{http://www.rdrop.com/users/paulmck/rclock/lockperf.2004.01.17a.pdf}
+\url{http://www.rdrop.com/users/paulmck/RCU/lockperf.2004.01.17a.pdf}
 [Viewed June 23, 2004]"
+,annotation="
+	Compares performance of RCU to that of other locking primitives
+	over a number of CPUs (x86, Opteron, Itanium, and PPC).
+"
 }
 
-@phdthesis{PaulEdwardMcKenneyPhD
-,author="Paul E. McKenney"
-,title="Exploiting Deferred Destruction:
-An Analysis of Read-Copy-Update Techniques
-in Operating System Kernels"
-,school="OGI School of Science and Engineering at
-Oregon Health and Sciences University"
+@unpublished{Sarma04a
+,Author="Dipankar Sarma"
+,Title="{[PATCH]} {RCU} for low latency (experimental)"
+,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"
+}
+
+@unpublished{Sarma04b
+,Author="Dipankar Sarma"
+,Title="Re: {[PATCH]} {RCU} for low latency (experimental)"
+,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"
+}
+
+@unpublished{Spraul04a
+,Author="Manfred Spraul"
+,Title="[RFC] 0/5 rcu lock update"
+,month="May"
 ,year="2004"
 ,note="Available:
-\url{http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf}
-[Viewed October 15, 2004]"
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=108546407726602&w=2}
+[Viewed June 23, 2004]"
+,annotation="
+	Hierarchical-bitmap patch for RCU infrastructure.
+"
+}
+
+@unpublished{Steiner04a
+,Author="Jack Steiner"
+,Title="Re: [Lse-tech] [RFC, PATCH] 1/5 rcu lock update:
+Add per-cpu batch counter"
+,month="May"
+,year="2004"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=108551764515332&w=2}
+[Viewed June 23, 2004]"
+,annotation={
+	RCU runs reasonably on a 512-CPU SGI using Manfred Spraul's patches,
+	which may be found at:
+	https://lkml.org/lkml/2004/5/20/49 (split vars into cachelines)
+	https://lkml.org/lkml/2004/5/22/114 (cpu_quiet() patch)
+	https://lkml.org/lkml/2004/5/25/24 (0/5)
+	https://lkml.org/lkml/2004/5/25/23 (1/5)
+		https://lkml.org/lkml/2004/5/25/265 (works for Jack)
+	https://lkml.org/lkml/2004/5/25/20 (2/5)
+	https://lkml.org/lkml/2004/5/25/22 (3/5)
+	https://lkml.org/lkml/2004/5/25/19 (4/5)
+	https://lkml.org/lkml/2004/5/25/21 (5/5)
+}
 }
 
 @Conference{Sarma04c
 ,Author="Dipankar Sarma and Paul E. McKenney"
-,Title="Making RCU Safe for Deep Sub-Millisecond Response Realtime Applications"
+,Title="Making {RCU} Safe for Deep Sub-Millisecond Response
+Realtime Applications"
 ,Booktitle="Proceedings of the 2004 USENIX Annual Technical Conference
 (FREENIX Track)"
 ,Publisher="USENIX Association"
 ,year="2004"
 ,month="June"
 ,pages="182-191"
+,annotation="
+	Describes and compares a number of modifications to the Linux RCU
+	implementation that make it friendly to realtime applications.
+"
 }
 
-@unpublished{JamesMorris04b
-,Author="James Morris"
-,Title="Recent Developments in {SELinux} Kernel Performance"
-,month="December"
+@phdthesis{PaulEdwardMcKenneyPhD
+,author="Paul E. McKenney"
+,title="Exploiting Deferred Destruction:
+An Analysis of Read-Copy-Update Techniques
+in Operating System Kernels"
+,school="OGI School of Science and Engineering at
+Oregon Health and Sciences University"
 ,year="2004"
 ,note="Available:
-\url{http://www.livejournal.com/users/james_morris/2153.html}
-[Viewed December 10, 2004]"
+\url{http://www.rdrop.com/users/paulmck/RCU/RCUdissertation.2004.07.14e1.pdf}
+[Viewed October 15, 2004]"
+,annotation="
+	Describes RCU implementations and presents design patterns
+	corresponding to common uses of RCU in several operating-system
+	kernels.
+"
 }
 
-@unpublished{PaulMcKenney05a
-,Author="Paul E. McKenney"
-,Title="{[RFC]} {RCU} and {CONFIG\_PREEMPT\_RT} progress"
-,month="May"
-,year="2005"
+@unpublished{PaulEMcKenney2004rcu:dereference
+,Author="Dipankar Sarma"
+,Title="{Re: RCU : Abstracted RCU dereferencing [5/5]}"
+,month="August"
+,year="2004"
 ,note="Available:
-\url{http://lkml.org/lkml/2005/5/9/185}
-[Viewed May 13, 2005]"
+\url{http://lkml.org/lkml/2004/8/6/237}
+[Viewed June 8, 2010]"
 ,annotation="
-	First publication of working lock-based deferred free patches
-	for the CONFIG_PREEMPT_RT environment.
+	Introduce rcu_dereference().
 "
 }
 
-@conference{PaulMcKenney05b
-,Author="Paul E. McKenney and Dipankar Sarma"
-,Title="Towards Hard Realtime Response from the Linux Kernel on SMP Hardware"
-,Booktitle="linux.conf.au 2005"
-,month="April"
-,year="2005"
-,address="Canberra, Australia"
+@unpublished{JimHouston04a
+,Author="Jim Houston"
+,Title="{[RFC\&PATCH] Alternative {RCU} implementation}"
+,month="August"
+,year="2004"
 ,note="Available:
-\url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
-[Viewed May 13, 2005]"
+\url{http://lkml.org/lkml/2004/8/30/87}
+[Viewed February 17, 2005]"
 ,annotation="
-	Realtime turns into making RCU yet more realtime friendly.
+	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.
 "
 }
 
-@conference{ThomasEHart2006a
-,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown"
-,Title="Making Lockless Synchronization Fast: Performance Implications
-of Memory Reclamation"
-,Booktitle="20\textsuperscript{th} {IEEE} International Parallel and
-Distributed Processing Symposium"
-,month="April"
-,year="2006"
-,day="25-29"
-,address="Rhodes, Greece"
+@unpublished{TomHart04a
+,Author="Thomas E. Hart"
+,Title="Master's Thesis: Applying Lock-free Techniques to the {Linux} Kernel"
+,month="October"
+,year="2004"
+,note="Available:
+\url{http://www.cs.toronto.edu/~tomhart/masters_thesis.html}
+[Viewed October 15, 2004]"
 ,annotation="
-	Compares QSBR (AKA "classic RCU"), HPBR, EBR, and lock-free
-	reference counting.
+	Proposes comparing RCU to lock-free methods for the Linux kernel.
 "
 }
 
-@Conference{PaulEMcKenney2006b
-,Author="Paul E. McKenney and Dipankar Sarma and Ingo Molnar and
-Suparna Bhattacharya"
-,Title="Extending RCU for Realtime and Embedded Workloads"
-,Booktitle="{Ottawa Linux Symposium}"
-,Month="July"
-,Year="2006"
-,pages="v2 123-138"
+@unpublished{Vaddagiri04a
+,Author="Srivatsa Vaddagiri"
+,Title="Subject: [RFC] Use RCU for tcp\_ehash lookup"
+,month="October"
+,year="2004"
 ,note="Available:
-\url{http://www.linuxsymposium.org/2006/index_2006.php}
-\url{http://www.rdrop.com/users/paulmck/RCU/OLSrtRCU.2006.08.11a.pdf}
-[Viewed January 1, 2007]"
+\url{http://marc.theaimsgroup.com/?t=109395731700004&r=1&w=2}
+[Viewed October 18, 2004]"
 ,annotation="
-	Described how to improve the -rt implementation of realtime RCU.
+	Srivatsa's RCU patch for tcp_ehash lookup.
 "
 }
 
-@unpublished{PaulEMcKenney2006c
-,Author="Paul E. McKenney"
-,Title="Sleepable {RCU}"
+@unpublished{Thirumalai04a
+,Author="Ravikiran Thirumalai"
+,Title="Subject: [patchset] Lockfree fd lookup 0 of 5"
 ,month="October"
-,day="9"
-,year="2006"
+,year="2004"
 ,note="Available:
-\url{http://lwn.net/Articles/202847/}
-Revised:
-\url{http://www.rdrop.com/users/paulmck/RCU/srcu.2007.01.14a.pdf}
-[Viewed August 21, 2006]"
+\url{http://marc.theaimsgroup.com/?t=109144217400003&r=1&w=2}
+[Viewed October 18, 2004]"
 ,annotation="
-	LWN article introducing SRCU.
+	Ravikiran's lockfree FD patch.
+"
+}
+
+@unpublished{Thirumalai04b
+,Author="Ravikiran Thirumalai"
+,Title="Subject: Re: [patchset] Lockfree fd lookup 0 of 5"
+,month="October"
+,year="2004"
+,note="Available:
+\url{http://marc.theaimsgroup.com/?l=linux-kernel&m=109152521410459&w=2}
+[Viewed October 18, 2004]"
+,annotation="
+	Ravikiran's lockfree FD patch.
+"
+}
+
+@unpublished{PaulEMcKenney2004rcu:assign:pointer
+,Author="Paul E. McKenney"
+,Title="{[PATCH 1/3] RCU: \url{rcu_assign_pointer()} removal of memory barriers}"
+,month="October"
+,year="2004"
+,note="Available:
+\url{http://lkml.org/lkml/2004/10/23/241}
+[Viewed June 8, 2010]"
+,annotation="
+	Introduce rcu_assign_pointer().
+"
+}
+
+@unpublished{JamesMorris04a
+,Author="James Morris"
+,Title="{[PATCH 2/3] SELinux} scalability - convert {AVC} to {RCU}"
+,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="
+	James Morris posts Kaigai Kohei's patch to LKML.
+"
+}
+
+@unpublished{JamesMorris04b
+,Author="James Morris"
+,Title="Recent Developments in {SELinux} Kernel Performance"
+,month="December"
+,year="2004"
+,note="Available:
+\url{http://www.livejournal.com/users/james_morris/2153.html}
+[Viewed December 10, 2004]"
+,annotation="
+	RCU helps SELinux performance.  ;-)  Made LWN.
+"
+}
+
+@unpublished{PaulMcKenney2005RCUSemantics
+,Author="Paul E. McKenney and Jonathan Walpole"
+,Title="{RCU} Semantics: A First Attempt"
+,month="January"
+,year="2005"
+,day="30"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/rcu-semantics.2005.01.30a.pdf}
+[Viewed December 6, 2009]"
+,annotation="
+	Early derivation of RCU semantics.
+"
+}
+
+@unpublished{PaulMcKenney2005e
+,Author="Paul E. McKenney"
+,Title="Real-Time Preemption and {RCU}"
+,month="March"
+,year="2005"
+,day="17"
+,note="Available:
+\url{http://lkml.org/lkml/2005/3/17/199}
+[Viewed September 5, 2005]"
+,annotation="
+	First posting showing how RCU can be safely adapted for
+	preemptable RCU read side critical sections.
+"
+}
+
+@unpublished{EsbenNeilsen2005a
+,Author="Esben Neilsen"
+,Title="Re: Real-Time Preemption and {RCU}"
+,month="March"
+,year="2005"
+,day="18"
+,note="Available:
+\url{http://lkml.org/lkml/2005/3/18/122}
+[Viewed March 30, 2006]"
+,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
+	and testing.
+"
+}
+
+@unpublished{TomHart05a
+,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown"
+,Title="Efficient Memory Reclamation is Necessary for Fast Lock-Free
+Data Structures"
+,month="March"
+,year="2005"
+,note="Available:
+\url{ftp://ftp.cs.toronto.edu/csrg-technical-reports/515/}
+[Viewed March 4, 2005]"
+,annotation="
+	Comparison of RCU, QBSR, and EBSR.  RCU wins for read-mostly
+	workloads.  ;-)
+"
+}
+
+@unpublished{JonCorbet2005DeprecateSyncKernel
+,Author="Jonathan Corbet"
+,Title="API change: synchronize_kernel() deprecated"
+,month="May"
+,day="3"
+,year="2005"
+,note="Available:
+\url{http://lwn.net/Articles/134484/}
+[Viewed May 3, 2005]"
+,annotation="
+	Jon Corbet describes deprecation of synchronize_kernel()
+	in favor of synchronize_rcu() and synchronize_sched().
+"
+}
+
+@unpublished{PaulMcKenney05a
+,Author="Paul E. McKenney"
+,Title="{[RFC]} {RCU} and {CONFIG\_PREEMPT\_RT} progress"
+,month="May"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/5/9/185}
+[Viewed May 13, 2005]"
+,annotation="
+	First publication of working lock-based deferred free patches
+	for the CONFIG_PREEMPT_RT environment.
+"
+}
+
+@conference{PaulMcKenney05b
+,Author="Paul E. McKenney and Dipankar Sarma"
+,Title="Towards Hard Realtime Response from the {Linux} Kernel on {SMP} Hardware"
+,Booktitle="linux.conf.au 2005"
+,month="April"
+,year="2005"
+,address="Canberra, Australia"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
+[Viewed May 13, 2005]"
+,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
+,Author="Paul E. McKenney"
+,Title="{Paul} {E.} {McKenney}"
+,month="May"
+,year="2005"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/}
+[Viewed May 25, 2005]"
+,annotation="
+	Paul McKenney's home page.
+"
+}
+
+@unpublished{PaulEMcKenneyRCUPage
+,Author="Paul E. McKenney"
+,Title="Read-Copy Update {(RCU)}"
+,month="May"
+,year="2005"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU}
+[Viewed May 25, 2005]"
+,annotation="
+	Paul McKenney's RCU page.
+"
+}
+
+@unpublished{JosephSeigh2005a
+,Author="Joseph Seigh"
+,Title="{RCU}+{SMR} (hazard pointers)"
+,month="July"
+,year="2005"
+,note="Personal communication"
+,annotation="
+	Joe Seigh announcing his atomic-ptr-plus project.
+	http://sourceforge.net/projects/atomic-ptr-plus/
+"
+}
+
+@unpublished{JosephSeigh2005b
+,Author="Joseph Seigh"
+,Title="Lock-free synchronization primitives"
+,month="July"
+,day="6"
+,year="2005"
+,note="Available:
+\url{http://sourceforge.net/projects/atomic-ptr-plus/}
+[Viewed August 8, 2005]"
+,annotation="
+	Joe Seigh's atomic-ptr-plus project.
+"
+}
+
+@unpublished{PaulMcKenney2005c
+,Author="Paul E.McKenney"
+,Title="{[RFC,PATCH] RCU} and {CONFIG\_PREEMPT\_RT} sane patch"
+,month="August"
+,day="1"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/8/1/155}
+[Viewed March 14, 2006]"
+,annotation="
+	First operating counter-based realtime RCU patch posted to LKML.
+"
+}
+
+@unpublished{PaulMcKenney2005d
+,Author="Paul E. McKenney"
+,Title="Re: [Fwd: Re: [patch] Real-Time Preemption, -RT-2.6.13-rc4-V0.7.52-01]"
+,month="August"
+,day="8"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/8/8/108}
+[Viewed March 14, 2006]"
+,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
+,Author="Paul E. McKenney"
+,Title="{[PATCH]} {RCU} torture testing"
+,month="October"
+,day="1"
+,year="2005"
+,note="Available:
+\url{http://lkml.org/lkml/2005/10/1/70}
+[Viewed March 14, 2006]"
+,annotation="
+	First rcutorture patch.
+"
+}
+
+@conference{ThomasEHart2006a
+,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown"
+,Title="Making Lockless Synchronization Fast: Performance Implications
+of Memory Reclamation"
+,Booktitle="20\textsuperscript{th} {IEEE} International Parallel and
+Distributed Processing Symposium"
+,month="April"
+,year="2006"
+,day="25-29"
+,address="Rhodes, Greece"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/hart_ipdps06.pdf}
+[Viewed April 28, 2008]"
+,annotation="
+	Compares QSBR, HPBR, EBR, and lock-free reference counting.
+	http://www.cs.toronto.edu/~tomhart/perflab/ipdps06.tgz
+"
+}
+
+@unpublished{NickPiggin2006radixtree
+,Author="Nick Piggin"
+,Title="[patch 3/3] radix-tree: {RCU} lockless readside"
+,month="June"
+,day="20"
+,year="2006"
+,note="Available:
+\url{http://lkml.org/lkml/2006/6/20/238}
+[Viewed March 25, 2008]"
+,annotation="
+	RCU-protected radix tree.
+"
+}
+
+@Conference{PaulEMcKenney2006b
+,Author="Paul E. McKenney and Dipankar Sarma and Ingo Molnar and
+Suparna Bhattacharya"
+,Title="Extending {RCU} for Realtime and Embedded Workloads"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="July"
+,Year="2006"
+,pages="v2 123-138"
+,note="Available:
+\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="
+	Described how to improve the -rt implementation of realtime RCU.
+"
+}
+
+@unpublished{WikipediaRCU
+,Author="Paul E. McKenney and Chris Purcell and Algae and Ben Schumin and
+Gaius Cornelius and Qwertyus and Neil Conway and Sbw and Blainster and
+Canis Rufus and Zoicon5 and Anome and Hal Eisen"
+,Title="Read-Copy Update"
+,month="July"
+,day="8"
+,year="2006"
+,note="Available:
+\url{http://en.wikipedia.org/wiki/Read-copy-update}
+[Viewed August 21, 2006]"
+,annotation="
+	Wikipedia RCU page as of July 8 2006.
+"
+}
+
+@Conference{NickPiggin2006LocklessPageCache
+,Author="Nick Piggin"
+,Title="A Lockless Pagecache in Linux---Introduction, Progress, Performance"
+,Booktitle="{Ottawa Linux Symposium}"
+,Month="July"
+,Year="2006"
+,pages="v2 249-254"
+,note="Available:
+\url{http://www.linuxsymposium.org/2006/view_abstract.php?content_key=184}
+[Viewed January 11, 2009]"
+,annotation="
+	Uses RCU-protected radix tree for a lockless page cache.
+"
+}
+
+@unpublished{PaulEMcKenney2006c
+,Author="Paul E. McKenney"
+,Title="Sleepable {RCU}"
+,month="October"
+,day="9"
+,year="2006"
+,note="Available:
+\url{http://lwn.net/Articles/202847/}
+Revised:
+\url{http://www.rdrop.com/users/paulmck/RCU/srcu.2007.01.14a.pdf}
+[Viewed August 21, 2006]"
+,annotation="
+	LWN article introducing SRCU.
 "
 }
 
@@ -637,29 +1399,301 @@ Revised:
 ,day="18"
 ,year="2006"
 ,note="Available:
-\url{http://www.nada.kth.se/~snilsson/public/papers/trash/trash.pdf}
-[Viewed February 24, 2007]"
+\url{http://www.nada.kth.se/~snilsson/publications/TRASH/trash.pdf}
+[Viewed March 4, 2011]"
+,annotation="
+	RCU-protected dynamic trie-hash combination.
+"
+}
+
+@unpublished{ChristophHellwig2006RCU2SRCU
+,Author="Christoph Hellwig"
+,Title="Re: {[-mm PATCH 1/4]} {RCU}: split classic rcu"
+,month="September"
+,day="28"
+,year="2006"
+,note="Available:
+\url{http://lkml.org/lkml/2006/9/28/160}
+[Viewed March 27, 2008]"
+}
+
+@unpublished{PaulEMcKenneyRCUusagePage
+,Author="Paul E. McKenney"
+,Title="{RCU} {Linux} Usage"
+,month="October"
+,year="2006"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/linuxusage.html}
+[Viewed January 14, 2007]"
+,annotation="
+	Paul McKenney's RCU page showing graphs plotting Linux-kernel
+	usage of RCU.
+"
+}
+
+@unpublished{PaulEMcKenneyRCUusageRawDataPage
+,Author="Paul E. McKenney"
+,Title="Read-Copy Update {(RCU)} Usage in {Linux} Kernel"
+,month="October"
+,year="2006"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html}
+[Viewed January 14, 2007]"
+,annotation="
+	Paul McKenney's RCU page showing Linux usage of RCU in tabular
+	form, with links to corresponding cscope databases.
+"
+}
+
+@unpublished{GauthamShenoy2006RCUrwlock
+,Author="Gautham R. Shenoy"
+,Title="[PATCH 4/5] lock\_cpu\_hotplug: Redesign - Lightweight implementation of lock\_cpu\_hotplug"
+,month="October"
+,year="2006"
+,day=26
+,note="Available:
+\url{http://lkml.org/lkml/2006/10/26/73}
+[Viewed January 26, 2009]"
+,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
+,Author="Jens Axboe"
+,Title="Re: [patch] cpufreq: mark \url{cpufreq_tsc()} as
+\url{core_initcall_sync}"
+,month="November"
+,year="2006"
+,day=17
+,note="Available:
+\url{http://lkml.org/lkml/2006/11/17/56}
+[Viewed May 28, 2007]"
+,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
+,Author="Oleg Nesterov"
+,Title="Re: [patch] cpufreq: mark {\tt cpufreq\_tsc()} as
+{\tt core\_initcall\_sync}"
+,month="November"
+,year="2006"
+,day=19
+,note="Available:
+\url{http://lkml.org/lkml/2006/11/19/69}
+[Viewed May 28, 2007]"
+,annotation="
+	First cut of QRCU.  Expanded/corrected versions followed.
+	Used to be OlegNesterov2007QRCU, now time-corrected.
+"
+}
+
+@unpublished{OlegNesterov2006aQRCU
+,Author="Oleg Nesterov"
+,Title="Re: [RFC, PATCH 1/2] qrcu: {"quick"} srcu implementation"
+,month="November"
+,year="2006"
+,day=30
+,note="Available:
+\url{http://lkml.org/lkml/2006/11/29/330}
+[Viewed November 26, 2008]"
+,annotation="
+	Expanded/corrected version of QRCU.
+	Used to be OlegNesterov2007aQRCU, now time-corrected.
+"
+}
+
+@unpublished{EvgeniyPolyakov2006RCUslowdown
+,Author="Evgeniy Polyakov"
+,Title="Badness in postponing work"
+,month="December"
+,year="2006"
+,day=05
+,note="Available:
+\url{http://www.ioremap.net/node/41}
+[Viewed October 28, 2008]"
+,annotation="
+	Using RCU as a pure delay leads to a 2.5x slowdown in skbs in
+	the Linux kernel.
+"
+}
+
+@inproceedings{ChrisMatthews2006ClusteredObjectsRCU
+,author = {Matthews, Chris and Coady, Yvonne and Appavoo, Jonathan}
+,title = {Portability events: a programming model for scalable system infrastructures}
+,booktitle = {PLOS '06: Proceedings of the 3rd workshop on Programming languages and operating systems}
+,year = {2006}
+,isbn = {1-59593-577-0}
+,pages = {11}
+,location = {San Jose, California}
+,doi = {http://doi.acm.org/10.1145/1215995.1216006}
+,publisher = {ACM}
+,address = {New York, NY, USA}
+,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}
+,title = {K42: an infrastructure for operating system research}
+,journal = {SIGOPS Oper. Syst. Rev.}
+,volume = {40}
+,number = {2}
+,year = {2006}
+,issn = {0163-5980}
+,pages = {34--42}
+,doi = {http://doi.acm.org/10.1145/1131322.1131333}
+,publisher = {ACM}
+,address = {New York, NY, USA}
+,annotation={
+	Describes relationship of K42 generations to RCU.
+}}
+
+# CoreyMinyard2007list_splice_rcu
+@unpublished{CoreyMinyard2007list:splice:rcu
+,Author="Corey Minyard and Paul E. McKenney"
+,Title="{[PATCH]} add an {RCU} version of list splicing"
+,month="January"
+,year="2007"
+,day=3
+,note="Available:
+\url{http://lkml.org/lkml/2007/1/3/112}
+[Viewed May 28, 2007]"
+,annotation="
+	Patch for list_splice_rcu().
+"
+}
+
+@unpublished{PaulEMcKenney2007rcubarrier
+,Author="Paul E. McKenney"
+,Title="{RCU} and Unloadable Modules"
+,month="January"
+,day="14"
+,year="2007"
+,note="Available:
+\url{http://lwn.net/Articles/217484/}
+[Viewed November 22, 2007]"
+,annotation="
+	LWN article introducing the rcu_barrier() primitive.
+"
+}
+
+@unpublished{PeterZijlstra2007SyncBarrier
+,Author="Peter Zijlstra and Ingo Molnar"
+,Title="{[PATCH 3/7]} barrier: a scalable synchonisation barrier"
+,month="January"
+,year="2007"
+,day=28
+,note="Available:
+\url{http://lkml.org/lkml/2007/1/28/34}
+[Viewed March 27, 2008]"
+,annotation="
+	RCU-like implementation for frequent updaters and rare readers(!).
+	Subsumed into QRCU.  Maybe...
+"
+}
+
+@unpublished{PaulEMcKenney2007BoostRCU
+,Author="Paul E. McKenney"
+,Title="Priority-Boosting {RCU} Read-Side Critical Sections"
+,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="
+	LWN article introducing RCU priority boosting.
+"
+}
+
+@unpublished{PaulMcKenney2007QRCUpatch
+,Author="Paul E. McKenney"
+,Title="{[PATCH]} {QRCU} with lockless fastpath"
+,month="February"
+,year="2007"
+,day=24
+,note="Available:
+\url{http://lkml.org/lkml/2007/2/25/18}
+[Viewed March 27, 2008]"
+,annotation="
+	Patch for QRCU supplying lock-free fast path.
+"
+}
+
+@article{JonathanAppavoo2007K42RCU
+,author = {Appavoo, Jonathan and Silva, Dilma Da and Krieger, Orran and Auslander, Marc and Ostrowski, Michal and Rosenburg, Bryan and Waterland, Amos and Wisniewski, Robert W. and Xenidis, Jimi and Stumm, Michael and Soares, Livio}
+,title = {Experience distributing objects in an SMMP OS}
+,journal = {ACM Trans. Comput. Syst.}
+,volume = {25}
+,number = {3}
+,year = {2007}
+,issn = {0734-2071}
+,pages = {6/1--6/52}
+,doi = {http://doi.acm.org/10.1145/1275517.1275518}
+,publisher = {ACM}
+,address = {New York, NY, USA}
+,annotation={
+	Role of RCU in K42.
+}}
+
+@conference{RobertOlsson2007Trash
+,Author="Robert Olsson and Stefan Nilsson"
+,Title="{TRASH}: A dynamic {LC}-trie and hash data structure"
+,booktitle="Workshop on High Performance Switching and Routing (HPSR'07)"
+,month="May"
+,year="2007"
+,note="Available:
+\url{http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?arnumber=4281239}
+[Viewed October 1, 2010]"
 ,annotation="
 	RCU-protected dynamic trie-hash combination.
 "
 }
 
-@unpublished{ThomasEHart2007a
-,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown and Jonathan Walpole"
-,Title="Performance of memory reclamation for lockless synchronization"
-,journal="J. Parallel Distrib. Comput."
+@conference{PeterZijlstra2007ConcurrentPagecacheRCU
+,Author="Peter Zijlstra"
+,Title="Concurrent Pagecache"
+,Booktitle="Linux Symposium"
+,month="June"
+,year="2007"
+,address="Ottawa, Canada"
+,note="Available:
+\url{http://ols.108.redhat.com/2007/Reprints/zijlstra-Reprint.pdf}
+[Viewed April 14, 2008]"
+,annotation="
+	Page-cache modifications permitting RCU readers and concurrent
+	updates.
+"
+}
+
+@unpublished{PaulEMcKenney2007whatisRCU
+,Author="Paul E. McKenney"
+,Title="What is {RCU}?"
 ,year="2007"
-,note="To appear in J. Parallel Distrib. Comput.
-       \url{doi=10.1016/j.jpdc.2007.04.010}"
+,month="07"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/whatisRCU.html}
+[Viewed July 6, 2007]"
 ,annotation={
-	Compares QSBR (AKA "classic RCU"), HPBR, EBR, and lock-free
-	reference counting.  Journal version of ThomasEHart2006a.
+	Describes RCU in Linux kernel.
 }
 }
 
 @unpublished{PaulEMcKenney2007QRCUspin
 ,Author="Paul E. McKenney"
-,Title="Using Promela and Spin to verify parallel algorithms"
+,Title="Using {Promela} and {Spin} to verify parallel algorithms"
 ,month="August"
 ,day="1"
 ,year="2007"
@@ -669,6 +1703,50 @@ Revised:
 ,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
+,Author="Paul E. McKenney and Hans-J. Boehm and Lawrence Crowl"
+,Title="C++ Data-Dependency Ordering: Atomics and Memory Model"
+,month="August"
+,day="3"
+,year="2007"
+,note="Available:
+\url{http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm}
+[Viewed December 7, 2009]"
+,annotation="
+	RCU for C++, parts 1 and 2.
+"
+}
+
+@unpublished{PaulEMcKenney2007WG21DDOannotation
+,Author="Paul E. McKenney and Lawrence Crowl"
+,Title="C++ Data-Dependency Ordering: Function Annotation"
+,month="September"
+,day="18"
+,year="2008"
+,note="Available:
+\url{http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2782.htm}
+[Viewed December 7, 2009]"
+,annotation="
+	RCU for C++, part 2, updated many times.
+"
+}
+
+@unpublished{PaulEMcKenney2007PreemptibleRCUPatch
+,Author="Paul E. McKenney"
+,Title="[PATCH RFC 0/9] {RCU}: Preemptible {RCU}"
+,month="September"
+,day="10"
+,year="2007"
+,note="Available:
+\url{http://lkml.org/lkml/2007/9/10/213}
+[Viewed October 25, 2007]"
+,annotation="
+	Final patch for preemptable RCU to -rt.  (Later patches were
+	to mainline, eventually incorporated.)
 "
 }
 
@@ -686,10 +1764,47 @@ Revised:
 "
 }
 
+@article{ThomasEHart2007a
+,Author="Thomas E. Hart and Paul E. McKenney and Angela Demke Brown and Jonathan Walpole"
+,Title="Performance of memory reclamation for lockless synchronization"
+,journal="J. Parallel Distrib. Comput."
+,volume={67}
+,number="12"
+,year="2007"
+,issn="0743-7315"
+,pages="1270--1285"
+,doi="http://dx.doi.org/10.1016/j.jpdc.2007.04.010"
+,publisher="Academic Press, Inc."
+,address="Orlando, FL, USA"
+,annotation={
+	Compares QSBR, HPBR, EBR, and lock-free reference counting.
+	Journal version of ThomasEHart2006a.
+}
+}
+
+# MathieuDesnoyers2007call_rcu_schedNeeded
+@unpublished{MathieuDesnoyers2007call:rcu:schedNeeded
+,Author="Mathieu Desnoyers"
+,Title="Re: [patch 1/2] {Linux} Kernel Markers - Support Multiple Probes"
+,month="December"
+,day="20"
+,year="2007"
+,note="Available:
+\url{http://lkml.org/lkml/2007/12/20/244}
+[Viewed March 27, 2008]"
+,annotation="
+	Request for call_rcu_sched() and rcu_barrier_sched().
+"
+}
+
+
 ########################################################################
 #
 #	"What is RCU?" LWN series.
 #
+#	http://lwn.net/Articles/262464/ (What is RCU, Fundamentally?)
+#	http://lwn.net/Articles/263130/ (What is RCU's Usage?)
+#	http://lwn.net/Articles/264090/ (What is RCU's API?)
 
 @unpublished{PaulEMcKenney2007WhatIsRCUFundamentally
 ,Author="Paul E. McKenney and Jonathan Walpole"
@@ -747,20 +1862,99 @@ Revised:
 #
 ########################################################################
 
+
+@unpublished{SteveRostedt2008dyntickRCUpatch
+,Author="Steven Rostedt and Paul E. McKenney"
+,Title="{[PATCH]} add support for dynamic ticks and preempt rcu"
+,month="January"
+,day="29"
+,year="2008"
+,note="Available:
+\url{http://lkml.org/lkml/2008/1/29/208}
+[Viewed March 27, 2008]"
+,annotation="
+	Patch that prevents preemptible RCU from unnecessarily waking
+	up dynticks-idle CPUs.
+"
+}
+
+@unpublished{PaulEMcKenney2008LKMLDependencyOrdering
+,Author="Paul E. McKenney"
+,Title="Re: [PATCH 02/22 -v7] Add basic support for gcc profiler instrumentation"
+,month="February"
+,day="1"
+,year="2008"
+,note="Available:
+\url{http://lkml.org/lkml/2008/2/2/255}
+[Viewed October 18, 2008]"
+,annotation="
+	Explanation of compilers violating dependency ordering.
+"
+}
+
+@Conference{PaulEMcKenney2008Beijing
+,Author="Paul E. McKenney"
+,Title="Introducing Technology Into {Linux} Or:
+Introducing your technology Into {Linux} will require introducing a
+lot of {Linux} into your technology!!!"
+,Booktitle="2008 Linux Developer Symposium - China"
+,Publisher="OSS China"
+,Month="February"
+,Year="2008"
+,Address="Beijing, China"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/TechIntroLinux.2008.02.19a.pdf}
+[Viewed August 12, 2008]"
+}
+
+@unpublished{PaulEMcKenney2008dynticksRCU
+,Author="Paul E. McKenney and Steven Rostedt"
+,Title="Integrating and Validating dynticks and Preemptable RCU"
+,month="April"
+,day="24"
+,year="2008"
+,note="Available:
+\url{http://lwn.net/Articles/279077/}
+[Viewed April 24, 2008]"
+,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"
+,Month="May"
 ,journal="IBM Systems Journal"
 ,volume="47"
 ,number="2"
-,pages="@@-@@"
+,pages="221-236"
+,note="Available:
+\url{http://www.research.ibm.com/journal/sj/472/guniguntala.pdf}
+[Viewed April 24, 2008]"
 ,annotation="
 	RCU, realtime RCU, sleepable RCU, performance.
 "
 }
 
+@unpublished{LaiJiangshan2008NewClassicAlgorithm
+,Author="Lai Jiangshan"
+,Title="[{RFC}][{PATCH}] rcu classic: new algorithm for callbacks-processing"
+,month="June"
+,day="3"
+,year="2008"
+,note="Available:
+\url{http://lkml.org/lkml/2008/6/2/539}
+[Viewed December 10, 2008]"
+,annotation="
+	Updated RCU classic algorithm.  Introduced multi-tailed list
+	for RCU callbacks and also pulling common code into
+	__call_rcu().
+"
+}
+
 @article{PaulEMcKenney2008RCUOSR
 ,author="Paul E. McKenney and Jonathan Walpole"
 ,title="Introducing technology into the {Linux} kernel: a case study"
@@ -778,6 +1972,52 @@ Revised:
 }
 }
 
+@unpublished{ManfredSpraul2008StateMachineRCU
+,Author="Manfred Spraul"
+,Title="[{RFC}, {PATCH}] state machine based rcu"
+,month="August"
+,day="21"
+,year="2008"
+,note="Available:
+\url{http://lkml.org/lkml/2008/8/21/336}
+[Viewed December 8, 2008]"
+,annotation="
+	State-based RCU.  One key thing that this patch does is to
+	separate the dynticks handling of NMIs and IRQs.
+"
+}
+
+@unpublished{ManfredSpraul2008dyntickIRQNMI
+,Author="Manfred Spraul"
+,Title="Re: [{RFC}, {PATCH}] v4 scalable classic {RCU} implementation"
+,month="September"
+,day="6"
+,year="2008"
+,note="Available:
+\url{http://lkml.org/lkml/2008/9/6/86}
+[Viewed December 8, 2008]"
+,annotation="
+	Manfred notes a fix required to my attempt to separate irq
+	and NMI processing for hierarchical RCU's dynticks interface.
+"
+}
+
+@techreport{PaulEMcKenney2011cyclicRCU
+,author="Paul E. McKenney"
+,title="Efficient Support of Consistent Cyclic Search With Read-Copy Update"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2008"
+,number="US Patent 7,426,511"
+,month="September"
+,pages="23"
+,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
 ,Author="Paul E. McKenney"
 ,Title="Hierarchical {RCU}"
@@ -793,6 +2033,21 @@ Revised:
 "
 }
 
+@unpublished{PaulEMcKenney2009BloatwatchRCU
+,Author="Paul E. McKenney"
+,Title="Re: [PATCH fyi] RCU: the bloatwatch edition"
+,month="January"
+,day="14"
+,year="2009"
+,note="Available:
+\url{http://lkml.org/lkml/2009/1/14/449}
+[Viewed January 15, 2009]"
+,annotation="
+	Small-footprint implementation of RCU for uniprocessor
+	embedded applications -- and also for exposition purposes.
+"
+}
+
 @conference{PaulEMcKenney2009MaliciousURCU
 ,Author="Paul E. McKenney"
 ,Title="Using a Malicious User-Level {RCU} to Torture {RCU}-Based Algorithms"
@@ -816,15 +2071,17 @@ Revised:
 ,year="2009"
 ,note="Available:
 \url{http://lkml.org/lkml/2009/2/5/572}
-\url{git://lttng.org/userspace-rcu.git}
+\url{http://lttng.org/urcu}
 [Viewed February 20, 2009]"
 ,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
 "
 }
 
-@unpublished{PaulEMcKenney2009BloatWatchRCU
+@unpublished{PaulEMcKenney2009LWNBloatWatchRCU
 ,Author="Paul E. McKenney"
 ,Title="{RCU}: The {Bloatwatch} Edition"
 ,month="March"
@@ -838,6 +2095,21 @@ Revised:
 "
 }
 
+@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
 ,Author="Paul E. McKenney"
 ,Title="[{PATCH} -tip 0/3] expedited 'big hammer' {RCU} grace periods"
@@ -852,6 +2124,20 @@ Revised:
 "
 }
 
+@unpublished{PaulEMcKenney2009fastRTRCU
+,Author="Paul E. McKenney"
+,Title="[{PATCH} {RFC} -tip 0/4] {RCU} cleanups and simplified preemptable {RCU}"
+,month="July"
+,day="23"
+,year="2009"
+,note="Available:
+\url{http://lkml.org/lkml/2009/7/23/294}
+[Viewed August 15, 2009]"
+,annotation="
+	First posting of simple and fast preemptable RCU.
+"
+}
+
 @unpublished{JoshTriplett2009RPHash
 ,Author="Josh Triplett"
 ,Title="Scalable concurrent hash tables via relativistic programming"
@@ -860,6 +2146,7 @@ Revised:
 ,note="Linux Plumbers Conference presentation"
 ,annotation="
 	RP fun with hash tables.
+	Superseded by JoshTriplett2010RPHash
 "
 }
 
@@ -872,4 +2159,323 @@ Revised:
 ,note="Available:
 \url{http://www.lttng.org/pub/thesis/desnoyers-dissertation-2009-12.pdf}
 [Viewed December 9, 2009]"
+,annotation={
+	Chapter 6 (page 97) covers user-level RCU.
+}
+}
+
+@unpublished{RelativisticProgrammingWiki
+,Author="Josh Triplett and Paul E. McKenney and Jonathan Walpole"
+,Title="Relativistic Programming"
+,month="September"
+,year="2009"
+,note="Available:
+\url{http://wiki.cs.pdx.edu/rp/}
+[Viewed December 9, 2009]"
+,annotation="
+	Main Relativistic Programming Wiki.
+"
+}
+
+@conference{PaulEMcKenney2009DeterministicRCU
+,Author="Paul E. McKenney"
+,Title="Deterministic Synchronization in Multicore Systems: the Role of {RCU}"
+,Booktitle="Eleventh Real Time Linux Workshop"
+,month="September"
+,year="2009"
+,address="Dresden, Germany"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/realtime/paper/DetSyncRCU.2009.08.18a.pdf}
+[Viewed January 14, 2009]"
+}
+
+@unpublished{PaulEMcKenney2009HuntingHeisenbugs
+,Author="Paul E. McKenney"
+,Title="Hunting Heisenbugs"
+,month="November"
+,year="2009"
+,day="1"
+,note="Available:
+\url{http://paulmck.livejournal.com/14639.html}
+[Viewed June 4, 2010]"
+,annotation="
+	Day-one bug in Tree RCU that took forever to track down.
+"
+}
+
+@unpublished{MathieuDesnoyers2009defer:rcu
+,Author="Mathieu Desnoyers"
+,Title="Kernel RCU: shrink the size of the struct rcu\_head"
+,month="December"
+,year="2009"
+,note="Available:
+\url{http://lkml.org/lkml/2009/10/18/129}
+[Viewed December 29, 2009]"
+,annotation="
+	Mathieu proposed defer_rcu() with fixed-size per-thread pool
+	of RCU callbacks.
+"
+}
+
+@unpublished{MathieuDesnoyers2009VerifPrePub
+,Author="Mathieu Desnoyers and Paul E. McKenney and Michel R. Dagenais"
+,Title="Multi-Core Systems Modeling for Formal Verification of Parallel Algorithms"
+,month="December"
+,year="2009"
+,note="Submitted to IEEE TPDS"
+,annotation="
+	OOMem model for Mathieu's user-level RCU mechanical proof of
+	correctness.
+"
+}
+
+@unpublished{MathieuDesnoyers2009URCUPrePub
+,Author="Mathieu Desnoyers and Paul E. McKenney and Alan Stern and Michel R. Dagenais and Jonathan Walpole"
+,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="
+	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
+,author = {Kannan, Hari}
+,title = {Ordering decoupled metadata accesses in multiprocessors}
+,booktitle = {MICRO 42: Proceedings of the 42nd Annual IEEE/ACM International Symposium on Microarchitecture}
+,year = {2009}
+,isbn = {978-1-60558-798-1}
+,pages = {381--390}
+,location = {New York, New York}
+,doi = {http://doi.acm.org/10.1145/1669112.1669161}
+,publisher = {ACM}
+,address = {New York, NY, USA}
+,annotation={
+	Uses RCU to protect metadata used in dynamic analysis.
+}}
+
+@conference{PaulEMcKenney2010SimpleOptRCU
+,Author="Paul E. McKenney"
+,Title="Simplicity Through Optimization"
+,Booktitle="linux.conf.au 2010"
+,month="January"
+,year="2010"
+,address="Wellington, New Zealand"
+,note="Available:
+\url{http://www.rdrop.com/users/paulmck/RCU/SimplicityThruOptimization.2010.01.21f.pdf}
+[Viewed October 10, 2010]"
+,annotation="
+	TREE_PREEMPT_RCU optimizations greatly simplified the old
+	PREEMPT_RCU implementation.
+"
+}
+
+@unpublished{PaulEMcKenney2010LockdepRCU
+,Author="Paul E. McKenney"
+,Title="Lockdep-{RCU}"
+,month="February"
+,year="2010"
+,day="1"
+,note="Available:
+\url{https://lwn.net/Articles/371986/}
+[Viewed June 4, 2010]"
+,annotation="
+	CONFIG_PROVE_RCU, or at least an early version.
+"
+}
+
+@unpublished{AviKivity2010KVM2RCU
+,Author="Avi Kivity"
+,Title="[{PATCH} 37/40] {KVM}: Bump maximum vcpu count to 64"
+,month="February"
+,year="2010"
+,note="Available:
+\url{http://www.mail-archive.com/kvm@vger.kernel.org/msg28640.html}
+[Viewed March 20, 2010]"
+,annotation="
+	Use of RCU permits KVM to increase the size of guest OSes from
+	16 CPUs to 64 CPUs.
+"
+}
+
+@unpublished{HerbertXu2010RCUResizeHash
+,Author="Herbert Xu"
+,Title="bridge: Add core IGMP snooping support"
+,month="February"
+,year="2010"
+,note="Available:
+\url{http://kerneltrap.com/mailarchive/linux-netdev/2010/2/26/6270589}
+[Viewed March 20, 2011]"
+,annotation={
+	Use a pair of list_head structures to support RCU-protected
+	resizable hash tables.
+}}
+
+@article{JoshTriplett2010RPHash
+,author="Josh Triplett and Paul E. McKenney and Jonathan Walpole"
+,title="Scalable Concurrent Hash Tables via Relativistic Programming"
+,journal="ACM Operating Systems Review"
+,year=2010
+,volume=44
+,number=3
+,month="July"
+,annotation={
+	RP fun with hash tables.
+	http://portal.acm.org/citation.cfm?id=1842733.1842750
+}}
+
+@unpublished{PaulEMcKenney2010RCUAPI
+,Author="Paul E. McKenney"
+,Title="The {RCU} {API}, 2010 Edition"
+,month="December"
+,day="8"
+,year="2010"
+,note="Available:
+\url{http://lwn.net/Articles/418853/}
+[Viewed December 8, 2010]"
+,annotation="
+	Includes updated software-engineering features.
+"
+}
+
+@mastersthesis{AndrejPodzimek2010masters
+,author="Andrej Podzimek"
+,title="Read-Copy-Update for OpenSolaris"
+,school="Charles University in Prague"
+,year="2010"
+,note="Available:
+\url{https://andrej.podzimek.org/thesis.pdf}
+[Viewed January 31, 2011]"
+,annotation={
+	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"
+,Title="Linux 2.6.38-rc1"
+,month="January"
+,year="2011"
+,note="Available:
+\url{https://lkml.org/lkml/2011/1/18/322}
+[Viewed March 4, 2011]"
+,annotation={
+	"The RCU-based name lookup is at the other end of the spectrum - the
+	absolute anti-gimmick. It's some seriously good stuff, and gets rid of
+	the last main global lock that really tends to hurt some kernel loads.
+	The dentry lock is no longer a big serializing issue. What's really
+	nice about it is that it actually improves performance a lot even for
+	single-threaded loads (on an SMP kernel), because it gets rid of some
+	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}
+,title = {Scalable Correct Memory Ordering via Relativistic Programming}
+,year = {2011}
+,number = {11-03}
+,institution = {Portland State University}
+,note = {\url{http://www.cs.pdx.edu/pdfs/tr1103.pdf}}
+}
+
+@inproceedings{PhilHoward2011RCUTMRBTree
+,author = {Philip W. Howard and Jonathan Walpole}
+,title = {A Relativistic Enhancement to Software Transactional Memory}
+,booktitle = {Proceedings of the 3rd USENIX conference on Hot topics in parallelism}
+,series = {HotPar'11}
+,year = {2011}
+,location = {Berkeley, CA}
+,pages = {1--6}
+,numpages = {6}
+,url = {http://www.usenix.org/event/hotpar11/tech/final_files/Howard.pdf}
+,publisher = {USENIX Association}
+,address = {Berkeley, CA, USA}
+}
+
+@techreport{PaulEMcKenney2011cyclicparallelRCU
+,author="Paul E. McKenney and Jonathan Walpole"
+,title="Efficient Support of Consistent Cyclic Search With Read-Copy Update and Parallel Updates"
+,institution="US Patent and Trademark Office"
+,address="Washington, DC"
+,year="2011"
+,number="US Patent 7,953,778"
+,month="May"
+,pages="34"
+,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
+,author = {Triplett, Josh and McKenney, Paul E. and Walpole, Jonathan}
+,title = {Resizable, Scalable, Concurrent Hash Tables via Relativistic Programming}
+,booktitle = {Proceedings of the 2011 USENIX Annual Technical Conference}
+,month = {June}
+,year = {2011}
+,pages = {145--158}
+,numpages = {14}
+,url={http://www.usenix.org/event/atc11/tech/final_files/atc11_proceedings.pdf}
+,publisher = {The USENIX Association}
+,address = {Portland, OR USA}
+} 
+
+@unpublished{PaulEMcKenney2011RCU3.0trainwreck
+,Author="Paul E. McKenney"
+,Title="3.0 and {RCU:} what went wrong"
+,month="July"
+,day="27"
+,year="2011"
+,note="Available:
+\url{http://lwn.net/Articles/453002/}
+[Viewed July 27, 2011]"
+,annotation="
+	Analysis of the RCU trainwreck in Linux kernel 3.0.
+"
+}
+
+@unpublished{NeilBrown2011MeetTheLockers
+,Author="Neil Brown"
+,Title="Meet the Lockers"
+,month="August"
+,day="3"
+,year="2011"
+,note="Available:
+\url{http://lwn.net/Articles/453685/}
+[Viewed September 2, 2011]"
+,annotation="
+	The Locker family as an analogy for locking, reference counting,
+	RCU, and seqlock.
+"
+}
+
+@article{MathieuDesnoyers2012URCU
+,Author="Mathieu Desnoyers and Paul E. McKenney and Alan Stern and Michel R. Dagenais and Jonathan Walpole"
+,Title="User-Level Implementations of Read-Copy Update"
+,journal="IEEE Transactions on Parallel and Distributed Systems"
+,volume={23}
+,year="2012"
+,issn="1045-9219"
+,pages="375-382"
+,doi="http://doi.ieeecomputersociety.org/10.1109/TPDS.2011.159"
+,publisher="IEEE Computer Society"
+,address="Los Alamitos, CA, USA"
+,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
+}
 }
diff --git a/Documentation/crc32.txt b/Documentation/crc32.txt
new file mode 100644
index 0000000..1885f7a
--- /dev/null
+++ b/Documentation/crc32.txt
@@ -0,0 +1,183 @@
+A brief CRC tutorial.
+
+A CRC is a long-division remainder.  You add the CRC to the message,
+and the whole thing (message+CRC) is a multiple of the given
+CRC polynomial.  To check the CRC, you can either check that the
+CRC matches the recomputed value, *or* you can check that the
+remainder computed on the message+CRC is 0.  This latter approach
+is used by a lot of hardware implementations, and is why so many
+protocols put the end-of-frame flag after the CRC.
+
+It's actually the same long division you learned in school, except that
+- We're working in binary, so the digits are only 0 and 1, and
+- When dividing polynomials, there are no carries.  Rather than add and
+  subtract, we just xor.  Thus, we tend to get a bit sloppy about
+  the difference between adding and subtracting.
+
+Like all division, the remainder is always smaller than the divisor.
+To produce a 32-bit CRC, the divisor is actually a 33-bit CRC polynomial.
+Since it's 33 bits long, bit 32 is always going to be set, so usually the
+CRC is written in hex with the most significant bit omitted.  (If you're
+familiar with the IEEE 754 floating-point format, it's the same idea.)
+
+Note that a CRC is computed over a string of *bits*, so you have
+to decide on the endianness of the bits within each byte.  To get
+the best error-detecting properties, this should correspond to the
+order they're actually sent.  For example, standard RS-232 serial is
+little-endian; the most significant bit (sometimes used for parity)
+is sent last.  And when appending a CRC word to a message, you should
+do it in the right order, matching the endianness.
+
+Just like with ordinary division, you proceed one digit (bit) at a time.
+Each step of the division you take one more digit (bit) of the dividend
+and append it to the current remainder.  Then you figure out the
+appropriate multiple of the divisor to subtract to being the remainder
+back into range.  In binary, this is easy - it has to be either 0 or 1,
+and to make the XOR cancel, it's just a copy of bit 32 of the remainder.
+
+When computing a CRC, we don't care about the quotient, so we can
+throw the quotient bit away, but subtract the appropriate multiple of
+the polynomial from the remainder and we're back to where we started,
+ready to process the next bit.
+
+A big-endian CRC written this way would be coded like:
+for (i = 0; i < input_bits; i++) {
+	multiple = remainder & 0x80000000 ? CRCPOLY : 0;
+	remainder = (remainder << 1 | next_input_bit()) ^ multiple;
+}
+
+Notice how, to get at bit 32 of the shifted remainder, we look
+at bit 31 of the remainder *before* shifting it.
+
+But also notice how the next_input_bit() bits we're shifting into
+the remainder don't actually affect any decision-making until
+32 bits later.  Thus, the first 32 cycles of this are pretty boring.
+Also, to add the CRC to a message, we need a 32-bit-long hole for it at
+the end, so we have to add 32 extra cycles shifting in zeros at the
+end of every message,
+
+These details lead to a standard trick: rearrange merging in the
+next_input_bit() until the moment it's needed.  Then the first 32 cycles
+can be precomputed, and merging in the final 32 zero bits to make room
+for the CRC can be skipped entirely.  This changes the code to:
+
+for (i = 0; i < input_bits; i++) {
+	remainder ^= next_input_bit() << 31;
+	multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
+	remainder = (remainder << 1) ^ multiple;
+}
+
+With this optimization, the little-endian code is particularly simple:
+for (i = 0; i < input_bits; i++) {
+	remainder ^= next_input_bit();
+	multiple = (remainder & 1) ? CRCPOLY : 0;
+	remainder = (remainder >> 1) ^ multiple;
+}
+
+The most significant coefficient of the remainder polynomial is stored
+in the least significant bit of the binary "remainder" variable.
+The other details of endianness have been hidden in CRCPOLY (which must
+be bit-reversed) and next_input_bit().
+
+As long as next_input_bit is returning the bits in a sensible order, we don't
+*have* to wait until the last possible moment to merge in additional bits.
+We can do it 8 bits at a time rather than 1 bit at a time:
+for (i = 0; i < input_bytes; i++) {
+	remainder ^= next_input_byte() << 24;
+	for (j = 0; j < 8; j++) {
+		multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
+		remainder = (remainder << 1) ^ multiple;
+	}
+}
+
+Or in little-endian:
+for (i = 0; i < input_bytes; i++) {
+	remainder ^= next_input_byte();
+	for (j = 0; j < 8; j++) {
+		multiple = (remainder & 1) ? CRCPOLY : 0;
+		remainder = (remainder >> 1) ^ multiple;
+	}
+}
+
+If the input is a multiple of 32 bits, you can even XOR in a 32-bit
+word at a time and increase the inner loop count to 32.
+
+You can also mix and match the two loop styles, for example doing the
+bulk of a message byte-at-a-time and adding bit-at-a-time processing
+for any fractional bytes at the end.
+
+To reduce the number of conditional branches, software commonly uses
+the byte-at-a-time table method, popularized by Dilip V. Sarwate,
+"Computation of Cyclic Redundancy Checks via Table Look-Up", Comm. ACM
+v.31 no.8 (August 1998) p. 1008-1013.
+
+Here, rather than just shifting one bit of the remainder to decide
+in the correct multiple to subtract, we can shift a byte at a time.
+This produces a 40-bit (rather than a 33-bit) intermediate remainder,
+and the correct multiple of the polynomial to subtract is found using
+a 256-entry lookup table indexed by the high 8 bits.
+
+(The table entries are simply the CRC-32 of the given one-byte messages.)
+
+When space is more constrained, smaller tables can be used, e.g. two
+4-bit shifts followed by a lookup in a 16-entry table.
+
+It is not practical to process much more than 8 bits at a time using this
+technique, because tables larger than 256 entries use too much memory and,
+more importantly, too much of the L1 cache.
+
+To get higher software performance, a "slicing" technique can be used.
+See "High Octane CRC Generation with the Intel Slicing-by-8 Algorithm",
+ftp://download.intel.com/technology/comms/perfnet/download/slicing-by-8.pdf
+
+This does not change the number of table lookups, but does increase
+the parallelism.  With the classic Sarwate algorithm, each table lookup
+must be completed before the index of the next can be computed.
+
+A "slicing by 2" technique would shift the remainder 16 bits at a time,
+producing a 48-bit intermediate remainder.  Rather than doing a single
+lookup in a 65536-entry table, the two high bytes are looked up in
+two different 256-entry tables.  Each contains the remainder required
+to cancel out the corresponding byte.  The tables are different because the
+polynomials to cancel are different.  One has non-zero coefficients from
+x^32 to x^39, while the other goes from x^40 to x^47.
+
+Since modern processors can handle many parallel memory operations, this
+takes barely longer than a single table look-up and thus performs almost
+twice as fast as the basic Sarwate algorithm.
+
+This can be extended to "slicing by 4" using 4 256-entry tables.
+Each step, 32 bits of data is fetched, XORed with the CRC, and the result
+broken into bytes and looked up in the tables.  Because the 32-bit shift
+leaves the low-order bits of the intermediate remainder zero, the
+final CRC is simply the XOR of the 4 table look-ups.
+
+But this still enforces sequential execution: a second group of table
+look-ups cannot begin until the previous groups 4 table look-ups have all
+been completed.  Thus, the processor's load/store unit is sometimes idle.
+
+To make maximum use of the processor, "slicing by 8" performs 8 look-ups
+in parallel.  Each step, the 32-bit CRC is shifted 64 bits and XORed
+with 64 bits of input data.  What is important to note is that 4 of
+those 8 bytes are simply copies of the input data; they do not depend
+on the previous CRC at all.  Thus, those 4 table look-ups may commence
+immediately, without waiting for the previous loop iteration.
+
+By always having 4 loads in flight, a modern superscalar processor can
+be kept busy and make full use of its L1 cache.
+
+Two more details about CRC implementation in the real world:
+
+Normally, appending zero bits to a message which is already a multiple
+of a polynomial produces a larger multiple of that polynomial.  Thus,
+a basic CRC will not detect appended zero bits (or bytes).  To enable
+a CRC to detect this condition, it's common to invert the CRC before
+appending it.  This makes the remainder of the message+crc come out not
+as zero, but some fixed non-zero value.  (The CRC of the inversion
+pattern, 0xffffffff.)
+
+The same problem applies to zero bits prepended to the message, and a
+similar solution is used.  Instead of starting the CRC computation with
+a remainder of 0, an initial remainder of all ones is used.  As long as
+you start the same way on decoding, it doesn't make a difference.
+
diff --git a/Documentation/cris/README b/Documentation/cris/README
index d9b0868..8dbdb1a 100644
--- a/Documentation/cris/README
+++ b/Documentation/cris/README
@@ -1,38 +1,34 @@
-Linux 2.4 on the CRIS architecture
-==================================
-$Id: README,v 1.7 2001/04/19 12:38:32 bjornw Exp $
+Linux on the CRIS architecture
+==============================
 
-This is a port of Linux 2.4 to Axis Communications ETRAX 100LX embedded 
-network CPU. For more information about CRIS and ETRAX please see further
-below.
+This is a port of Linux to Axis Communications ETRAX 100LX,
+ETRAX FS and ARTPEC-3 embedded network CPUs.
+
+For more information about CRIS and ETRAX please see further below.
 
 In order to compile this you need a version of gcc with support for the
-ETRAX chip family. Please see this link for more information on how to 
+ETRAX chip family. Please see this link for more information on how to
 download the compiler and other tools useful when building and booting
 software for the ETRAX platform:
 
-http://developer.axis.com/doc/software/devboard_lx/install-howto.html
-
-<more specific information should come in this document later>
+http://developer.axis.com/wiki/doku.php?id=axis:install-howto-2_20
 
 What is CRIS ?
 --------------
 
 CRIS is an acronym for 'Code Reduced Instruction Set'. It is the CPU
 architecture in Axis Communication AB's range of embedded network CPU's,
-called ETRAX. The latest CPU is called ETRAX 100LX, where LX stands for
-'Linux' because the chip was designed to be a good host for the Linux
-operating system.
+called ETRAX.
 
 The ETRAX 100LX chip
 --------------------
 
-For reference, please see the press-release:
+For reference, please see the following link:
 
-http://www.axis.com/news/us/001101_etrax.htm
+http://www.axis.com/products/dev_etrax_100lx/index.htm
 
-The ETRAX 100LX is a 100 MIPS processor with 8kB cache, MMU, and a very broad 
-range of  built-in interfaces, all with modern scatter/gather DMA.
+The ETRAX 100LX is a 100 MIPS processor with 8kB cache, MMU, and a very broad
+range of built-in interfaces, all with modern scatter/gather DMA.
 
 Memory interfaces:
 
@@ -51,20 +47,28 @@ I/O interfaces:
 	* SCSI
 	* two parallel-ports
 	* two generic 8-bit ports
-	
-	(not all interfaces are available at the same time due to chip pin 
+
+	(not all interfaces are available at the same time due to chip pin
          multiplexing)
 
-The previous version of the ETRAX, the ETRAX 100, sits in almost all of
-Axis shipping thin-servers like the Axis 2100 web camera or the ETRAX 100
-developer-board. It lacks an MMU so the Linux we run on that is a version
-of uClinux (Linux 2.0 without MM-support) ported to the CRIS architecture.
-The new Linux 2.4 port has full MM and needs a CPU with an MMU, so it will
-not run on the ETRAX 100.
+ETRAX 100LX is CRISv10 architecture.
+
+
+The ETRAX FS and ARTPEC-3 chips
+-------------------------------
 
-A version of the Axis developer-board with ETRAX 100LX (running Linux
-2.4) is now available. For more information please see developer.axis.com.
+The ETRAX FS is a 200MHz 32-bit RISC processor with on-chip 16kB
+I-cache and 16kB D-cache and with a wide range of device interfaces
+including multiple high speed serial ports and an integrated USB 1.1 PHY.
 
+The ARTPEC-3 is a variant of the ETRAX FS with additional IO-units
+used by the Axis Communications network cameras.
+
+See below link for more information:
+
+http://www.axis.com/products/dev_etrax_fs/index.htm
+
+ETRAX FS and ARTPEC-3 are both CRISv32 architectures.
 
 Bootlog
 -------
@@ -182,10 +186,6 @@ SwapFree:            0 kB
 -rwxr-xr-x  1 342      100         16252  Jan 01 00:00 telnetd
 
 
-(All programs are statically linked to the libc at this point - we have not ported the
- shared libraries yet)
-
-
 
 
 
diff --git a/Documentation/edac.txt b/Documentation/edac.txt
index 249822c..fdcc49f 100644
--- a/Documentation/edac.txt
+++ b/Documentation/edac.txt
@@ -334,8 +334,8 @@ Sdram memory scrubbing rate:
 
 	Reading the file will return the actual scrubbing rate employed.
 
-	If configuration fails or memory scrubbing is not implemented, the value
-	of the attribute file will be -1.
+	If configuration fails or memory scrubbing is not implemented, accessing
+	that attribute will fail.
 
 
 
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 1bea46a..381385c 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -510,3 +510,12 @@ Why:	The pci_scan_bus_parented() interface creates a new root bus.  The
 	convert to using pci_scan_root_bus() so they can supply a list of
 	bus resources when the bus is created.
 Who:	Bjorn Helgaas <bhelgaas@google.com>
+
+----------------------------
+
+What:	kmap_atomic(page, km_type)
+When:	3.5
+Why:	The old kmap_atomic() with two arguments is deprecated, we only
+	keep it for backward compatibility for few cycles and then drop it.
+Who:	Cong Wang <amwang@redhat.com>
+
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 4840334..2550754 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -224,6 +224,7 @@ Code  Seq#(hex)	Include File		Comments
 'j'	00-3F	linux/joystick.h
 'k'	00-0F	linux/spi/spidev.h	conflict!
 'k'	00-05	video/kyro.h		conflict!
+'k'	10-17	linux/hsi/hsi_char.h	HSI character device
 'l'	00-3F	linux/tcfs_fs.h		transparent cryptographic file system
 					<http://web.archive.org/web/*/http://mikonos.dia.unisa.it/tcfs>
 'l'	40-7F	linux/udf_fs_i.h	in development:
diff --git a/Documentation/laptops/sony-laptop.txt b/Documentation/laptops/sony-laptop.txt
index 2bd4e82..0d5ac7f 100644
--- a/Documentation/laptops/sony-laptop.txt
+++ b/Documentation/laptops/sony-laptop.txt
@@ -17,6 +17,11 @@ subsystem. See the logs of acpid or /proc/acpi/event and
 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
+module.  For example the "FN/E" key combination (EJECTCD on some models)
+generates the scancode 20 (0x14).
+
 Backlight control:
 ------------------
 If your laptop model supports it, you will find sysfs files in the
diff --git a/Documentation/power/basic-pm-debugging.txt b/Documentation/power/basic-pm-debugging.txt
index 40a4c65..262acf5 100644
--- a/Documentation/power/basic-pm-debugging.txt
+++ b/Documentation/power/basic-pm-debugging.txt
@@ -15,7 +15,7 @@ test at least a couple of times in a row for confidence.  [This is necessary,
 because some problems only show up on a second attempt at suspending and
 resuming the system.]  Moreover, hibernating in the "reboot" and "shutdown"
 modes causes the PM core to skip some platform-related callbacks which on ACPI
-systems might be necessary to make hibernation work.  Thus, if you machine fails
+systems might be necessary to make hibernation work.  Thus, if your machine fails
 to hibernate or resume in the "reboot" mode, you should try the "platform" mode:
 
 # echo platform > /sys/power/disk
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
index 6ccb68f..ebd7490 100644
--- a/Documentation/power/freezing-of-tasks.txt
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -120,10 +120,10 @@ So in practice, the 'at all' may become a 'why freeze kernel threads?' and
 freezing user threads I don't find really objectionable."
 
 Still, there are kernel threads that may want to be freezable.  For example, if
-a kernel that belongs to a device driver accesses the device directly, it in
-principle needs to know when the device is suspended, so that it doesn't try to
-access it at that time.  However, if the kernel thread is freezable, it will be
-frozen before the driver's .suspend() callback is executed and it will be
+a kernel thread that belongs to a device driver accesses the device directly, it
+in principle needs to know when the device is suspended, so that it doesn't try
+to access it at that time.  However, if the kernel thread is freezable, it will
+be frozen before the driver's .suspend() callback is executed and it will be
 thawed after the driver's .resume() callback has run, so it won't be accessing
 the device while it's suspended.
 
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 8fb1ba7..a0b9d8e 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -3,7 +3,7 @@ Ramoops oops/panic logger
 
 Sergiu Iordache <sergiu@chromium.org>
 
-Updated: 8 August 2011
+Updated: 17 November 2011
 
 0. Introduction
 
@@ -71,6 +71,6 @@ timestamp and a new line. The dump then continues with the actual data.
 
 4. Reading the data
 
-The dump data can be read from memory (through /dev/mem or other means).
-Getting the module parameters, which are needed in order to parse the data, can
-be done through /sys/module/ramoops/parameters/* .
+The dump data can be read from the pstore filesystem. The format for these
+files is "dmesg-ramoops-N", where N is the record number in memory. To delete
+a stored record from RAM, simply unlink the respective pstore file.
diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
new file mode 100644
index 0000000..23ff734
--- /dev/null
+++ b/Documentation/remoteproc.txt
@@ -0,0 +1,324 @@
+Remote Processor Framework
+
+1. Introduction
+
+Modern SoCs typically have heterogeneous remote processor devices in asymmetric
+multiprocessing (AMP) configurations, which may be running different instances
+of operating system, whether it's Linux or any other flavor of real-time OS.
+
+OMAP4, for example, has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP.
+In a typical configuration, the dual cortex-A9 is running Linux in a SMP
+configuration, and each of the other three cores (two M3 cores and a DSP)
+is running its own instance of RTOS in an AMP configuration.
+
+The remoteproc framework allows different platforms/architectures to
+control (power on, load firmware, power off) those remote processors while
+abstracting the hardware differences, so the entire driver doesn't need to be
+duplicated. In addition, this framework also adds rpmsg virtio devices
+for remote processors that supports this kind of communication. This way,
+platform-specific remoteproc drivers only need to provide a few low-level
+handlers, and then all rpmsg drivers will then just work
+(for more information about the virtio-based rpmsg bus and its drivers,
+please read Documentation/rpmsg.txt).
+
+2. User API
+
+  int rproc_boot(struct rproc *rproc)
+    - Boot a remote processor (i.e. load its firmware, power it on, ...).
+      If the remote processor is already powered on, this function immediately
+      returns (successfully).
+      Returns 0 on success, and an appropriate error value otherwise.
+      Note: to use this function you should already have a valid rproc
+      handle. There are several ways to achieve that cleanly (devres, pdata,
+      the way remoteproc_rpmsg.c does this, or, if this becomes prevalent, we
+      might also consider using dev_archdata for this). See also
+      rproc_get_by_name() below.
+
+  void rproc_shutdown(struct rproc *rproc)
+    - Power off a remote processor (previously booted with rproc_boot()).
+      In case @rproc is still being used by an additional user(s), then
+      this function will just decrement the power refcount and exit,
+      without really powering off the device.
+      Every call to rproc_boot() must (eventually) be accompanied by a call
+      to rproc_shutdown(). Calling rproc_shutdown() redundantly is a bug.
+      Notes:
+      - we're not decrementing the rproc's refcount, only the power refcount.
+        which means that the @rproc handle stays valid even after
+        rproc_shutdown() returns, and users can still use it with a subsequent
+        rproc_boot(), if needed.
+      - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly
+        because rproc_shutdown() _does not_ decrement the refcount of @rproc.
+        To decrement the refcount of @rproc, use rproc_put() (but _only_ if
+        you acquired @rproc using rproc_get_by_name()).
+
+  struct rproc *rproc_get_by_name(const char *name)
+    - Find an rproc handle using the remote processor's name, and then
+      boot it. If it's already powered on, then just immediately return
+      (successfully). Returns the rproc handle on success, and NULL on failure.
+      This function increments the remote processor's refcount, so always
+      use rproc_put() to decrement it back once rproc isn't needed anymore.
+      Note: currently rproc_get_by_name() and rproc_put() are not used anymore
+      by the rpmsg bus and its drivers. We need to scrutinize the use cases
+      that still need them, and see if we can migrate them to use the non
+      name-based boot/shutdown interface.
+
+  void rproc_put(struct rproc *rproc)
+    - Decrement @rproc's power refcount and shut it down if it reaches zero
+      (essentially by just calling rproc_shutdown), and then decrement @rproc's
+      validity refcount too.
+      After this function returns, @rproc may _not_ be used anymore, and its
+      handle should be considered invalid.
+      This function should be called _iff_ the @rproc handle was grabbed by
+      calling rproc_get_by_name().
+
+3. Typical usage
+
+#include <linux/remoteproc.h>
+
+/* in case we were given a valid 'rproc' handle */
+int dummy_rproc_example(struct rproc *my_rproc)
+{
+	int ret;
+
+	/* let's power on and boot our remote processor */
+	ret = rproc_boot(my_rproc);
+	if (ret) {
+		/*
+		 * something went wrong. handle it and leave.
+		 */
+	}
+
+	/*
+	 * our remote processor is now powered on... give it some work
+	 */
+
+	/* let's shut it down now */
+	rproc_shutdown(my_rproc);
+}
+
+4. API for implementors
+
+  struct rproc *rproc_alloc(struct device *dev, const char *name,
+				const struct rproc_ops *ops,
+				const char *firmware, int len)
+    - Allocate a new remote processor handle, but don't register
+      it yet. Required parameters are the underlying device, the
+      name of this remote processor, platform-specific ops handlers,
+      the name of the firmware to boot this rproc with, and the
+      length of private data needed by the allocating rproc driver (in bytes).
+
+      This function should be used by rproc implementations during
+      initialization of the remote processor.
+      After creating an rproc handle using this function, and when ready,
+      implementations should then call rproc_register() to complete
+      the registration of the remote processor.
+      On success, the new rproc is returned, and on failure, NULL.
+
+      Note: _never_ directly deallocate @rproc, even if it was not registered
+      yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free().
+
+  void rproc_free(struct rproc *rproc)
+    - Free an rproc handle that was allocated by rproc_alloc.
+      This function should _only_ be used if @rproc was only allocated,
+      but not registered yet.
+      If @rproc was already successfully registered (by calling
+      rproc_register()), then use rproc_unregister() instead.
+
+  int rproc_register(struct rproc *rproc)
+    - Register @rproc with the remoteproc framework, after it has been
+      allocated with rproc_alloc().
+      This is called by the platform-specific rproc implementation, whenever
+      a new remote processor device is probed.
+      Returns 0 on success and an appropriate error code otherwise.
+      Note: this function initiates an asynchronous firmware loading
+      context, which will look for virtio devices supported by the rproc's
+      firmware.
+      If found, those virtio devices will be created and added, so as a result
+      of registering this remote processor, additional virtio drivers might get
+      probed.
+      Currently, though, we only support a single RPMSG virtio vdev per remote
+      processor.
+
+  int rproc_unregister(struct rproc *rproc)
+    - Unregister a remote processor, and decrement its refcount.
+      If its refcount drops to zero, then @rproc will be freed. If not,
+      it will be freed later once the last reference is dropped.
+
+      This function should be called when the platform specific rproc
+      implementation decides to remove the rproc device. it should
+      _only_ be called if a previous invocation of rproc_register()
+      has completed successfully.
+
+      After rproc_unregister() returns, @rproc is _not_ valid anymore and
+      it shouldn't be used. More specifically, don't call rproc_free()
+      or try to directly free @rproc after rproc_unregister() returns;
+      none of these are needed, and calling them is a bug.
+
+      Returns 0 on success and -EINVAL if @rproc isn't valid.
+
+5. Implementation callbacks
+
+These callbacks should be provided by platform-specific remoteproc
+drivers:
+
+/**
+ * struct rproc_ops - platform-specific device handlers
+ * @start:	power on the device and boot it
+ * @stop:	power off the device
+ * @kick:	kick a virtqueue (virtqueue id given as a parameter)
+ */
+struct rproc_ops {
+	int (*start)(struct rproc *rproc);
+	int (*stop)(struct rproc *rproc);
+	void (*kick)(struct rproc *rproc, int vqid);
+};
+
+Every remoteproc implementation should at least provide the ->start and ->stop
+handlers. If rpmsg functionality is also desired, then the ->kick handler
+should be provided as well.
+
+The ->start() handler takes an rproc handle and should then power on the
+device and boot it (use rproc->priv to access platform-specific private data).
+The boot address, in case needed, can be found in rproc->bootaddr (remoteproc
+core puts there the ELF entry point).
+On success, 0 should be returned, and on failure, an appropriate error code.
+
+The ->stop() handler takes an rproc handle and powers the device down.
+On success, 0 is returned, and on failure, an appropriate error code.
+
+The ->kick() handler takes an rproc handle, and an index of a virtqueue
+where new message was placed in. Implementations should interrupt the remote
+processor and let it know it has pending messages. Notifying remote processors
+the exact virtqueue index to look in is optional: it is easy (and not
+too expensive) to go through the existing virtqueues and look for new buffers
+in the used rings.
+
+6. Binary Firmware Structure
+
+At this point remoteproc only supports ELF32 firmware binaries. However,
+it is quite expected that other platforms/devices which we'd want to
+support with this framework will be based on different binary formats.
+
+When those use cases show up, we will have to decouple the binary format
+from the framework core, so we can support several binary formats without
+duplicating common code.
+
+When the firmware is parsed, its various segments are loaded to memory
+according to the specified device address (might be a physical address
+if the remote processor is accessing memory directly).
+
+In addition to the standard ELF segments, most remote processors would
+also include a special section which we call "the resource table".
+
+The resource table contains system resources that the remote processor
+requires before it should be powered on, such as allocation of physically
+contiguous memory, or iommu mapping of certain on-chip peripherals.
+Remotecore will only power up the device after all the resource table's
+requirement are met.
+
+In addition to system resources, the resource table may also contain
+resource entries that publish the existence of supported features
+or configurations by the remote processor, such as trace buffers and
+supported virtio devices (and their configurations).
+
+Currently the resource table is just an array of:
+
+/**
+ * struct fw_resource - describes an entry from the resource section
+ * @type: resource type
+ * @id: index number of the resource
+ * @da: device address of the resource
+ * @pa: physical address of the resource
+ * @len: size, in bytes, of the resource
+ * @flags: properties of the resource, e.g. iommu protection required
+ * @reserved: must be 0 atm
+ * @name: name of resource
+ */
+struct fw_resource {
+	u32 type;
+	u32 id;
+	u64 da;
+	u64 pa;
+	u32 len;
+	u32 flags;
+	u8 reserved[16];
+	u8 name[48];
+} __packed;
+
+Some resources entries are mere announcements, where the host is informed
+of specific remoteproc configuration. Other entries require the host to
+do something (e.g. reserve a requested resource) and possibly also reply
+by overwriting a member inside 'struct fw_resource' with info about the
+allocated resource.
+
+Different resource entries use different members of this struct,
+with different meanings. This is pretty limiting and error-prone,
+so the plan is to move to variable-length TLV-based resource entries,
+where each resource will begin with a type and length fields, followed by
+its own specific structure.
+
+Here are the resource types that are currently being used:
+
+/**
+ * enum fw_resource_type - types of resource entries
+ *
+ * @RSC_CARVEOUT:   request for allocation of a physically contiguous
+ *		    memory region.
+ * @RSC_DEVMEM:     request to iommu_map a memory-based peripheral.
+ * @RSC_TRACE:	    announces the availability of a trace buffer into which
+ *		    the remote processor will be writing logs. In this case,
+ *		    'da' indicates the device address where logs are written to,
+ *		    and 'len' is the size of the trace buffer.
+ * @RSC_VRING:	    request for allocation of a virtio vring (address should
+ *		    be indicated in 'da', and 'len' should contain the number
+ *		    of buffers supported by the vring).
+ * @RSC_VIRTIO_DEV: announces support for a virtio device, and serves as
+ *		    the virtio header. 'da' contains the virtio device
+ *		    features, 'pa' holds the virtio guest features (host
+ *		    will write them here after they're negotiated), 'len'
+ *		    holds the virtio status, and 'flags' holds the virtio
+ *		    device id (currently only VIRTIO_ID_RPMSG is supported).
+ */
+enum fw_resource_type {
+	RSC_CARVEOUT	= 0,
+	RSC_DEVMEM	= 1,
+	RSC_TRACE	= 2,
+	RSC_VRING	= 3,
+	RSC_VIRTIO_DEV	= 4,
+	RSC_VIRTIO_CFG	= 5,
+};
+
+Most of the resource entries share the basic idea of address/length
+negotiation with the host: the firmware usually asks for memory
+of size 'len' bytes, and the host needs to allocate it and provide
+the device/physical address (when relevant) in 'da'/'pa' respectively.
+
+If the firmware is compiled with hard coded device addresses, and
+can't handle dynamically allocated 'da' values, then the 'da' field
+will contain the expected device addresses (today we actually only support
+this scheme, as there aren't yet any use cases for dynamically allocated
+device addresses).
+
+We also expect that platform-specific resource entries will show up
+at some point. When that happens, we could easily add a new RSC_PLAFORM
+type, and hand those resources to the platform-specific rproc driver to handle.
+
+7. Virtio and remoteproc
+
+The firmware should provide remoteproc information about virtio devices
+that it supports, and their configurations: a RSC_VIRTIO_DEV resource entry
+should specify the virtio device id, and subsequent RSC_VRING resource entries
+should indicate the vring size (i.e. how many buffers do they support) and
+where should they be mapped (i.e. which device address). Note: the alignment
+between the consumer and producer parts of the vring is assumed to be 4096.
+
+At this point we only support a single virtio rpmsg device per remote
+processor, but the plan is to remove this limitation. In addition, once we
+move to TLV-based resource table, the plan is to have a single RSC_VIRTIO
+entry per supported virtio device, which will include the virtio header,
+the vrings information and the virtio config space.
+
+Of course, RSC_VIRTIO resource entries are only good enough for static
+allocation of virtio devices. Dynamic allocations will also be made possible
+using the rpmsg bus (similar to how we already do dynamic allocations of
+rpmsg channels; read more about it in rpmsg.txt).
diff --git a/Documentation/rpmsg.txt b/Documentation/rpmsg.txt
new file mode 100644
index 0000000..409d9f9
--- /dev/null
+++ b/Documentation/rpmsg.txt
@@ -0,0 +1,293 @@
+Remote Processor Messaging (rpmsg) Framework
+
+Note: this document describes the rpmsg bus and how to write rpmsg drivers.
+To learn how to add rpmsg support for new platforms, check out remoteproc.txt
+(also a resident of Documentation/).
+
+1. Introduction
+
+Modern SoCs typically employ heterogeneous remote processor devices in
+asymmetric multiprocessing (AMP) configurations, which may be running
+different instances of operating system, whether it's Linux or any other
+flavor of real-time OS.
+
+OMAP4, for example, has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP.
+Typically, the dual cortex-A9 is running Linux in a SMP configuration,
+and each of the other three cores (two M3 cores and a DSP) is running
+its own instance of RTOS in an AMP configuration.
+
+Typically AMP remote processors employ dedicated DSP codecs and multimedia
+hardware accelerators, and therefore are often used to offload CPU-intensive
+multimedia tasks from the main application processor.
+
+These remote processors could also be used to control latency-sensitive
+sensors, drive random hardware blocks, or just perform background tasks
+while the main CPU is idling.
+
+Users of those remote processors can either be userland apps (e.g. multimedia
+frameworks talking with remote OMX components) or kernel drivers (controlling
+hardware accessible only by the remote processor, reserving kernel-controlled
+resources on behalf of the remote processor, etc..).
+
+Rpmsg is a virtio-based messaging bus that allows kernel drivers to communicate
+with remote processors available on the system. In turn, drivers could then
+expose appropriate user space interfaces, if needed.
+
+When writing a driver that exposes rpmsg communication to userland, please
+keep in mind that remote processors might have direct access to the
+system's physical memory and other sensitive hardware resources (e.g. on
+OMAP4, remote cores and hardware accelerators may have direct access to the
+physical memory, gpio banks, dma controllers, i2c bus, gptimers, mailbox
+devices, hwspinlocks, etc..). Moreover, those remote processors might be
+running RTOS where every task can access the entire memory/devices exposed
+to the processor. To minimize the risks of rogue (or buggy) userland code
+exploiting remote bugs, and by that taking over the system, it is often
+desired to limit userland to specific rpmsg channels (see definition below)
+it can send messages on, and if possible, minimize how much control
+it has over the content of the messages.
+
+Every rpmsg device is a communication channel with a remote processor (thus
+rpmsg devices are called channels). Channels are identified by a textual name
+and have a local ("source") rpmsg address, and remote ("destination") rpmsg
+address.
+
+When a driver starts listening on a channel, its rx callback is bound with
+a unique rpmsg local address (a 32-bit integer). This way when inbound messages
+arrive, the rpmsg core dispatches them to the appropriate driver according
+to their destination address (this is done by invoking the driver's rx handler
+with the payload of the inbound message).
+
+
+2. User API
+
+  int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len);
+   - sends a message across to the remote processor on a given channel.
+     The caller should specify the channel, the data it wants to send,
+     and its length (in bytes). The message will be sent on the specified
+     channel, i.e. its source and destination address fields will be
+     set to the channel's src and dst addresses.
+
+     In case there are no TX buffers available, the function will block until
+     one becomes available (i.e. until the remote processor consumes
+     a tx buffer and puts it back on virtio's used descriptor ring),
+     or a timeout of 15 seconds elapses. When the latter happens,
+     -ERESTARTSYS is returned.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst);
+   - sends a message across to the remote processor on a given channel,
+     to a destination address provided by the caller.
+     The caller should specify the channel, the data it wants to send,
+     its length (in bytes), and an explicit destination address.
+     The message will then be sent to the remote processor to which the
+     channel belongs, using the channel's src address, and the user-provided
+     dst address (thus the channel's dst address will be ignored).
+
+     In case there are no TX buffers available, the function will block until
+     one becomes available (i.e. until the remote processor consumes
+     a tx buffer and puts it back on virtio's used descriptor ring),
+     or a timeout of 15 seconds elapses. When the latter happens,
+     -ERESTARTSYS is returned.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+							void *data, int len);
+   - sends a message across to the remote processor, using the src and dst
+     addresses provided by the user.
+     The caller should specify the channel, the data it wants to send,
+     its length (in bytes), and explicit source and destination addresses.
+     The message will then be sent to the remote processor to which the
+     channel belongs, but the channel's src and dst addresses will be
+     ignored (and the user-provided addresses will be used instead).
+
+     In case there are no TX buffers available, the function will block until
+     one becomes available (i.e. until the remote processor consumes
+     a tx buffer and puts it back on virtio's used descriptor ring),
+     or a timeout of 15 seconds elapses. When the latter happens,
+     -ERESTARTSYS is returned.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len);
+   - sends a message across to the remote processor on a given channel.
+     The caller should specify the channel, the data it wants to send,
+     and its length (in bytes). The message will be sent on the specified
+     channel, i.e. its source and destination address fields will be
+     set to the channel's src and dst addresses.
+
+     In case there are no TX buffers available, the function will immediately
+     return -ENOMEM without waiting until one becomes available.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+   - sends a message across to the remote processor on a given channel,
+     to a destination address provided by the user.
+     The user should specify the channel, the data it wants to send,
+     its length (in bytes), and an explicit destination address.
+     The message will then be sent to the remote processor to which the
+     channel belongs, using the channel's src address, and the user-provided
+     dst address (thus the channel's dst address will be ignored).
+
+     In case there are no TX buffers available, the function will immediately
+     return -ENOMEM without waiting until one becomes available.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+							void *data, int len);
+   - sends a message across to the remote processor, using source and
+     destination addresses provided by the user.
+     The user should specify the channel, the data it wants to send,
+     its length (in bytes), and explicit source and destination addresses.
+     The message will then be sent to the remote processor to which the
+     channel belongs, but the channel's src and dst addresses will be
+     ignored (and the user-provided addresses will be used instead).
+
+     In case there are no TX buffers available, the function will immediately
+     return -ENOMEM without waiting until one becomes available.
+     The function can only be called from a process context (for now).
+     Returns 0 on success and an appropriate error value on failure.
+
+  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
+		void (*cb)(struct rpmsg_channel *, void *, int, void *, u32),
+		void *priv, u32 addr);
+   - every rpmsg address in the system is bound to an rx callback (so when
+     inbound messages arrive, they are dispatched by the rpmsg bus using the
+     appropriate callback handler) by means of an rpmsg_endpoint struct.
+
+     This function allows drivers to create such an endpoint, and by that,
+     bind a callback, and possibly some private data too, to an rpmsg address
+     (either one that is known in advance, or one that will be dynamically
+     assigned for them).
+
+     Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
+     is already created for them when they are probed by the rpmsg bus
+     (using the rx callback they provide when they registered to the rpmsg bus).
+
+     So things should just work for simple drivers: they already have an
+     endpoint, their rx callback is bound to their rpmsg address, and when
+     relevant inbound messages arrive (i.e. messages which their dst address
+     equals to the src address of their rpmsg channel), the driver's handler
+     is invoked to process it.
+
+     That said, more complicated drivers might do need to allocate
+     additional rpmsg addresses, and bind them to different rx callbacks.
+     To accomplish that, those drivers need to call this function.
+     Drivers should provide their channel (so the new endpoint would bind
+     to the same remote processor their channel belongs to), an rx callback
+     function, an optional private data (which is provided back when the
+     rx callback is invoked), and an address they want to bind with the
+     callback. If addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
+     dynamically assign them an available rpmsg address (drivers should have
+     a very good reason why not to always use RPMSG_ADDR_ANY here).
+
+     Returns a pointer to the endpoint on success, or NULL on error.
+
+  void rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
+   - destroys an existing rpmsg endpoint. user should provide a pointer
+     to an rpmsg endpoint that was previously created with rpmsg_create_ept().
+
+  int register_rpmsg_driver(struct rpmsg_driver *rpdrv);
+   - registers an rpmsg driver with the rpmsg bus. user should provide
+     a pointer to an rpmsg_driver struct, which contains the driver's
+     ->probe() and ->remove() functions, an rx callback, and an id_table
+     specifying the names of the channels this driver is interested to
+     be probed with.
+
+  void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv);
+   - unregisters an rpmsg driver from the rpmsg bus. user should provide
+     a pointer to a previously-registered rpmsg_driver struct.
+     Returns 0 on success, and an appropriate error value on failure.
+
+
+3. Typical usage
+
+The following is a simple rpmsg driver, that sends an "hello!" message
+on probe(), and whenever it receives an incoming message, it dumps its
+content to the console.
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+
+static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
+						void *priv, u32 src)
+{
+	print_hex_dump(KERN_INFO, "incoming message:", DUMP_PREFIX_NONE,
+						16, 1, data, len, true);
+}
+
+static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
+{
+	int err;
+
+	dev_info(&rpdev->dev, "chnl: 0x%x -> 0x%x\n", rpdev->src, rpdev->dst);
+
+	/* send a message on our channel */
+	err = rpmsg_send(rpdev, "hello!", 6);
+	if (err) {
+		pr_err("rpmsg_send failed: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __devexit rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+{
+	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
+}
+
+static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
+	{ .name	= "rpmsg-client-sample" },
+	{ },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
+
+static struct rpmsg_driver rpmsg_sample_client = {
+	.drv.name	= KBUILD_MODNAME,
+	.drv.owner	= THIS_MODULE,
+	.id_table	= rpmsg_driver_sample_id_table,
+	.probe		= rpmsg_sample_probe,
+	.callback	= rpmsg_sample_cb,
+	.remove		= __devexit_p(rpmsg_sample_remove),
+};
+
+static int __init init(void)
+{
+	return register_rpmsg_driver(&rpmsg_sample_client);
+}
+module_init(init);
+
+static void __exit fini(void)
+{
+	unregister_rpmsg_driver(&rpmsg_sample_client);
+}
+module_exit(fini);
+
+Note: a similar sample which can be built and loaded can be found
+in samples/rpmsg/.
+
+4. Allocations of rpmsg channels:
+
+At this point we only support dynamic allocations of rpmsg channels.
+
+This is possible only with remote processors that have the VIRTIO_RPMSG_F_NS
+virtio device feature set. This feature bit means that the remote
+processor supports dynamic name service announcement messages.
+
+When this feature is enabled, creation of rpmsg devices (i.e. channels)
+is completely dynamic: the remote processor announces the existence of a
+remote rpmsg service by sending a name service message (which contains
+the name and rpmsg addr of the remote service, see struct rpmsg_ns_msg).
+
+This message is then handled by the rpmsg bus, which in turn dynamically
+creates and registers an rpmsg channel (which represents the remote service).
+If/when a relevant rpmsg driver is registered, it will be immediately probed
+by the bus, and can then start sending messages to the remote service.
+
+The plan is also to add static creation of rpmsg channels via the virtio
+config space, but it's not implemented yet.
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 8c20fbd..6d78841 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -601,6 +601,8 @@ can be ORed together:
         instead of using the one provided by the hardware.
  512 - A kernel warning has occurred.
 1024 - A module from drivers/staging was loaded.
+2048 - The system is working around a severe firmware bug.
+4096 - An out-of-tree module has been loaded.
 
 ==============================================================
 
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 96f0ee8..9c11d97 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -28,6 +28,7 @@ Currently, these files are in /proc/sys/vm:
 - dirty_writeback_centisecs
 - drop_caches
 - extfrag_threshold
+- extra_free_kbytes
 - hugepages_treat_as_movable
 - hugetlb_shm_group
 - laptop_mode
@@ -168,6 +169,21 @@ fragmentation index is <= extfrag_threshold. The default value is 500.
 
 ==============================================================
 
+extra_free_kbytes
+
+This parameter tells the VM to keep extra free memory between the threshold
+where background reclaim (kswapd) kicks in, and the threshold where direct
+reclaim (by allocating processes) kicks in.
+
+This is useful for workloads that require low latency memory allocations
+and have a bounded burstiness in memory allocations, for example a
+realtime application that receives and transmits network traffic
+(causing in-kernel memory allocations) with a maximum total message burst
+size of 200MB may need 200MB of extra free memory to avoid direct reclaim
+related latencies.
+
+==============================================================
+
 hugepages_treat_as_movable
 
 This parameter is only useful when kernelcore= is specified at boot time to
diff --git a/Documentation/trace/uprobetracer.txt b/Documentation/trace/uprobetracer.txt
new file mode 100644
index 0000000..457932f
--- /dev/null
+++ b/Documentation/trace/uprobetracer.txt
@@ -0,0 +1,93 @@
+		Uprobe-tracer: Uprobe-based Event Tracing
+		=========================================
+                 Documentation is written by Srikar Dronamraju
+
+Overview
+--------
+These events are similar to kprobe based events.
+To enable this feature, build your kernel with CONFIG_UPROBE_EVENTS=y.
+
+Similar to the kprobe-event tracer, this doesn't need to be activated via
+current_tracer. Instead of that, add probe points via
+/sys/kernel/debug/tracing/uprobe_events, and enable it via
+/sys/kernel/debug/tracing/events/uprobes/<EVENT>/enabled.
+
+
+Synopsis of uprobe_tracer
+-------------------------
+  p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS]	: Set a probe
+
+ GRP		: Group name. If omitted, use "uprobes" for it.
+ EVENT		: Event name. If omitted, the event name is generated
+		  based on SYMBOL+offs.
+ PATH		: path to an executable or a library.
+ SYMBOL[+offs]	: Symbol+offset where the probe is inserted.
+
+ FETCHARGS	: Arguments. Each probe can have up to 128 args.
+  %REG		: Fetch register REG
+
+Event Profiling
+---------------
+ You can check the total number of probe hits and probe miss-hits via
+/sys/kernel/debug/tracing/uprobe_profile.
+ The first column is event name, the second is the number of probe hits,
+the third is the number of probe miss-hits.
+
+Usage examples
+--------------
+To add a probe as a new event, write a new definition to uprobe_events
+as below.
+
+  echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
+
+ This sets a uprobe at an offset of 0x4245c0 in the executable /bin/bash
+
+
+  echo > /sys/kernel/debug/tracing/uprobe_events
+
+ This clears all probe points.
+
+The following example shows how to dump the instruction pointer and %ax
+a register at the probed text address.  Here we are trying to probe
+function zfree in /bin/zsh
+
+    # cd /sys/kernel/debug/tracing/
+    # cat /proc/`pgrep  zsh`/maps | grep /bin/zsh | grep r-xp
+    00400000-0048a000 r-xp 00000000 08:03 130904 /bin/zsh
+    # objdump -T /bin/zsh | grep -w zfree
+    0000000000446420 g    DF .text  0000000000000012  Base        zfree
+
+0x46420 is the offset of zfree in object /bin/zsh that is loaded at
+0x00400000. Hence the command to probe would be :
+
+    # echo 'p /bin/zsh:0x46420 %ip %ax' > uprobe_events
+
+We can see the events that are registered by looking at the uprobe_events
+file.
+
+    # cat uprobe_events
+    p:uprobes/p_zsh_0x46420 /bin/zsh:0x0000000000046420
+
+Right after definition, each event is disabled by default. For tracing these
+events, you need to enable it by:
+
+    # echo 1 > events/uprobes/enable
+
+Lets disable the event after sleeping for some time.
+    # sleep 20
+    # echo 0 > events/uprobes/enable
+
+And you can see the traced information via /sys/kernel/debug/tracing/trace.
+
+    # cat trace
+    # tracer: nop
+    #
+    #           TASK-PID    CPU#    TIMESTAMP  FUNCTION
+    #              | |       |          |         |
+                 zsh-24842 [006] 258544.995456: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
+                 zsh-24842 [007] 258545.000270: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
+                 zsh-24842 [002] 258545.043929: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
+                 zsh-24842 [004] 258547.046129: p_zsh_0x46420: (0x446420) arg1=446421 arg2=79
+
+Each line shows us probes were triggered for a pid 24842 with ip being
+0x446421 and contents of ax register being 79.
diff --git a/MAINTAINERS b/MAINTAINERS
index 89b70df..56818fe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4126,6 +4126,7 @@ F:	fs/partitions/ldm.*
 
 LogFS
 M:	Joern Engel <joern@logfs.org>
+M:	Prasad Joshi <prasadjoshi.linux@gmail.com>
 L:	logfs@logfs.org
 W:	logfs.org
 S:	Maintained
@@ -4359,6 +4360,12 @@ S:	Supported
 F:	Documentation/mips/
 F:	arch/mips/
 
+MIPS/LANTIQ
+M:	John Crispin <blogic@openwrt.org>
+M:	Thomas Langer <thomas.langer@lantiq.com>
+S:	Maintained
+F:	arch/mips/lantiq/*
+
 MISCELLANEOUS MCA-SUPPORT
 M:	James Bottomley <James.Bottomley@HansenPartnership.com>
 S:	Maintained
@@ -4467,6 +4474,14 @@ L:	alsa-devel@alsa-project.org
 W:	http://www.native-instruments.com
 F:	sound/usb/caiaq/
 
+NATIVE LINUX KVM TOOL
+M:	Pekka Enberg <penberg@kernel.org>
+M:	Sasha Levin <levinsasha928@gmail.com>
+M:	Asias He <asias.hejun@gmail.com>
+L:	kvm@vger.kernel.org
+S:	Maintained
+F:	tools/kvm/
+
 NCP FILESYSTEM
 M:	Petr Vandrovec <petr@vandrovec.name>
 S:	Odd Fixes
@@ -5548,6 +5563,13 @@ S:	Supported
 F:	drivers/base/regmap/
 F:	include/linux/regmap.h
 
+REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
+M:	Ohad Ben-Cohen <ohad@wizery.com>
+S:	Maintained
+F:	drivers/remoteproc/
+F:	Documentation/remoteproc.txt
+F:	include/linux/remoteproc.txt
+
 RFKILL
 M:	Johannes Berg <johannes@sipsolutions.net>
 L:	linux-wireless@vger.kernel.org
@@ -6296,6 +6318,11 @@ M:	Mori Hess <fmhess@users.sourceforge.net>
 S:	Odd Fixes
 F:	drivers/staging/comedi/
 
+STAGING - CONEXANT CX25821 PCIE BRIDGE
+L:	linux-media@vger.kernel.org
+S:	Odd Fixes
+F:	drivers/staging/cx25821/
+
 STAGING - CRYSTAL HD VIDEO DECODER
 M:	Naren Sankar <nsankar@broadcom.com>
 M:	Jarod Wilson <jarod@wilsonet.com>
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 0000000..57a4ae3
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,206 @@
+Name		SHA1
+----		----
+origin		dcd6c92267155e70a94b3927bce681ce74b80d1f
+fixes		371de6e4e0042adf4f9b54c414154f57414ddd37
+kbuild-current	fa0ad6575f6d459e215dded90b10cc455a889145
+arm-current	f1cfd9e3636914a76c2f279a3eec6f9ce56fa8ce
+m68k-current	3bd9e50b4297b0d85bb86a8f2ade941c0f9c21fd
+powerpc-merge	ebb7f616abf6ee11603e6b63aa6c5f84c80a17d0
+52xx-and-virtex-current	c49f8789f532ae39019135ca038e9bc0d15aaa4a
+sparc		e51e07e0ac7e3ff847d640f41b7527db04d4a4e7
+scsi-rc-fixes	6f6c2aa33b915c574543f176dee89d7aefc115c1
+net		3d8fe98f8d5cb303d907d8f94ea6dc1f9a1d8b7a
+sound-current	f0e48b6bd4e407459715240cd241ddb6b89bdf81
+pci-current	8b6a5af92c03b363df050da906480085b6cd6e00
+wireless	4f3d09de38d234ce7ffba5ec5a7e6704f983d375
+driver-core.current	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+tty.current	6b3da11b3c36fdafce3a72e0e90d6c4e99e9aad5
+usb.current	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+staging.current	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+char-misc.current	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+cpufreq-current	5983fe2b29df5885880d7fa3b91aca306c7564ef
+input-current	52965cc012f7a3cf35f06485ec275ebf3b3fddae
+md-current	307729c8bc5b5a41361af8af95906eee7552acb1
+audit-current	def57543418a5f47debae28a0a9dea2effc11692
+crypto-current	51fc6dc8f948047364f7d42a4ed89b416c6cc0a3
+ide		0ab3d8b3213c8bb55370b11fcc5321ee4f2c5e92
+dwmw2		244dc4e54b73567fae7f8fd9ba56584be9375442
+sh-current	21d41f2b312231536cf981c960c83cc4493c0293
+rmobile-current	a408baea3cdd2a7b5ad3d70080dff454b8883f62
+devicetree-current	c89810acbcf48c7004e912b2b4b862480b2d00e1
+spi-current	e583685e998e52ebbf31fadf7d8470ae69951660
+gpio-current	94bd2442d25454a874e070d871f50f4ce9d57101
+arm		33710e3ab91daa75da760da2317ceac4f2fa6ac9
+arm-soc		0db991de1efea474365e269f68d3c2d291ccf9df
+arm-perf	7e9523fb7da963a6df31aa327cfe0956ebc3efa8
+at91		8748dfae379573cdbea4e765b55e608a1764f918
+davinci		fe0d42203cb5616eeff68b14576a0f7e2dd56625
+linux-spec	5111711d3ed8f4f1012cac3ec3f2b463b549fbfd
+omap		322a8b034003c0d46d39af85bf24fee27b902f48
+pxa		19d6c13b56a78b3757e747f469285c2a546d634a
+samsung		9edb240696bacd53f4331119d2dfd13d4cd4852f
+s5p		e9148158809037638d5bd6081101045911287d41
+tegra		bdd01cc5544bbf11ac6230a5409dd22021fe4005
+xilinx		b85a3ef4ac65169b65fd2fe9bec7912bbf475ba4
+blackfin	c2bc3a316a7281f67e36b34dac2802cbe36a9128
+c6x		166c0eaedfc3157dc1394c27e827add19f05fb27
+cris		ea78f5b898555ddfbab494c7755130362fe3cf46
+hexagon		110b3723837f231b7dda418df975bcc09e780825
+ia64		65cc21b4523e94d5640542a818748cd3be8cd6b4
+m68k		3bd9e50b4297b0d85bb86a8f2ade941c0f9c21fd
+m68knommu	1f7034b9616e6f14dc7b6aa280210421428f31af
+microblaze	ccb19d263fd1c9e34948e2158c53eacbff369344
+mips		8551715e982c8e1cd51d4fafd571a8988acbe3a6
+openrisc	b6fd41e29dea9c6753b1843a77e50433e6123bcb
+parisc		fc99a914318c60cc9fa9c7347529f4e07dec67d8
+powerpc		ef88e3911c0e0301e73fa3b3b2567aabdbe17cc4
+4xx		ef88e3911c0e0301e73fa3b3b2567aabdbe17cc4
+52xx-and-virtex	c1395f4cf4a1944236f0f28cdf718c4aacc88f2d
+galak		ef88e3911c0e0301e73fa3b3b2567aabdbe17cc4
+s390		f16330316321d1c388d13096f6858f5d2dac29dc
+sh		b9a3acf46afdafc601947136f63e9dd228cd86e8
+rmobile		b58c580d996655658975aa8042b43b7d579f3986
+sparc-next	e4e11180dfa545233e5145919b75b7fac88638df
+tile		0c90547b4a3fcee184db4d54ffc1a4fb17fd54d6
+unicore32	099469502f62fbe0d7e4f0b83a2f22538367f734
+xtensa		29aced688a9321e3da04a45ad94407dfe7c903f7
+ceph		83eb26af0db71f2dfe551405c55d982288fa6178
+cifs		acbbb76a26648dfae6fed0989879e40d75692bfc
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	1209f493087b887500a64a11a1488018795a28e1
+ext3		46fe44ce8777f087aa8ad4a2605fdcfb9c2d63af
+ext4		d50f2ab6f050311dbf7b8f5501b25f0bf64a439b
+fatfs		710d4403a45c4040a9aa86971d50958f5ae6ed40
+fuse		03c9693db0ea5605e23b8f4bbd4f7212a6fad982
+gfs2		53999bf34d55981328f8ba9def558d3e104d6e36
+hfsplus		6596528e391ad978a6a120142cba97a1d7324cb6
+jfs		1c8007b0769d37aa5fcb343b383b0af89ade2f71
+logfs		21f3eb832ba8902a29746a602015410b0b471622
+nfs		90a4c0f51e8e44111a926be6f4c87af3938a79c3
+nfsd		7a6ef8c72314f254c107c6a9ed7cb201961ee05a
+nilfs2		93ee7a9340d64f20295aacc3fb6a22b759323280
+ocfs2		939255798a468e1a92f03546de6e87be7b491e57
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	3d4a1c80c4eb97187b3a61b3bfa8c804327f7a45
+v9fs		f766619db2be059cd0dbba8a36176fe01a29d588
+ubifs		1f4f43475f1295dc41c18684e59deea9b6d46045
+xfs		d060646436233912178e6b9e3a7f30a41214220f
+vfs		a25a2b84098eb5e001cb8086603d692aa95bf2ec
+vfs-scale	32385c7cf60a78375b63afc4f02001df84dfd1a0
+pci		76ccc297018d25d55b789bbd508861ef1e2cdb0c
+hid		f62f61917d72c1fb0101ad405664f6fc868d676b
+i2c		ccb19d263fd1c9e34948e2158c53eacbff369344
+bjdooks-i2c	fc84fe19ffb9eee7e6b3301bc6cd45b22f187bd7
+jdelvare-hwmon	ccb19d263fd1c9e34948e2158c53eacbff369344
+hwmon-staging	80b0ed57342619e4088afa8316b3f9ca10a07b18
+kernel-doc	5851bad5cfb66ec0e9a980725e54db8a7248570d
+docs		5c24d8b2bf99ee93049a6f8154ef9cd7897a6e36
+v4l-dvb		36be126cb0ebe3000a65c1049f339a3e882a9a47
+kbuild		b1e0fba0558cf80c9699346ef186e6baecb1c5a2
+kconfig		eae1c36aea9cfe4d123b8af3ffe54109c6579810
+libata		b73fa4630e63e4d23407181c2bc0a54777bd0ce8
+infiniband	1583676d9e3f97371eaa726c4e061f9b23f43c44
+acpi		b9bf644cbedc765d785b06fffef1cb173f60a07d
+cpupowerutils	498ca793d90aef8ad38a852a969c257f62832738
+ieee1394	2ca526bf4953380abfe5dff455e356967b239c70
+ubi		805a6af8dba5dfdd35ec35dc52ec0122400b2610
+dlm		60f98d1839376d30e13f3e452dce2433fad3060e
+scsi		76ffe8a3f766358a0ade543153625b3e4e66159d
+target-updates	895f3022523361e9b383cf48f51feb1f7d5e7e53
+target-merge	a42d985bd5b234da8b61347a78dc3057bf7bb94d
+ibft		935a9fee51c945b8942be2d7b4bae069167b4886
+slave-dma	e08b881a69d638175bfa99b5af4d72b731633ea7
+async_tx	21ef4b8b7a7d59a995bf44382de38c95587767d4
+net-next	356b95424cfb456e14a59eaa579422ce014c424b
+wireless-next	c3b5003b628d8e373262bee42c7260d6a799c73e
+bluetooth	c5993de864d96b3656e9fca38c377b130105d97a
+mtd		f5eee485f4579c7917a6fa09c6307451545ae427
+l2-mtd		8be70fd5d23cc0ddc6e46667a99d40fa3588778a
+crypto		b85a088f15f2070b7180735a231012843a5ac96c
+sound		387dbd13befb26d60c219e6a470feaf377f06c0b
+sound-asoc	14af6bd555d54d182d181edc75fc3f0a13dc730e
+cpufreq		6c523c614c13b84a3dc64f7a56d6855b03e6b292
+rr		53999bf34d55981328f8ba9def558d3e104d6e36
+input		dab78d7924598ea4031663dd10db814e2e324928
+input-mt	02f8c6aee8df3cdc935e9bdd4f2d020306035dbe
+lsm		ca05a99a54db1db5bca72eccb5866d2a86f8517f
+block		b3021da8f53746bc90d76694ded195e890ac9220
+device-mapper	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		74411c04540404a1ff29d254584ef393e150aeda
+battery		913272b3864d6da89c70d9fc2c30ccb57794b369
+mmc		0ac9f78ca95dd31e2008ed6a89d2bc21a03a8225
+kgdb		880ba694f6161ce4b8e14fb7be64f3d446dd5ae6
+slab		a1450d6360329464fae6dcca68b5906998328b70
+uclinux		5e442a493fc59fa536c76db1fff5b49ca36a88c5
+md		307729c8bc5b5a41361af8af95906eee7552acb1
+mfd		74d836c4142e5d100f8d9a1b2ee3003c2ed7109d
+hdlc		4a6908a3a050aacc9c3a2f36b276b46c0629ad91
+drm		095f979a539245a46b9e5d600ec9c720b4d928e5
+fbdev		f787f32e67e00b072f46b2ae3c454d2c0a1fcdb7
+viafb		4ce36bbb0497bdd3d6b8682175e5c58745b7acdd
+omap_dss2	9a9016832d2601a290db4dce6dd55552bdae5b1a
+regulator	0c437c4ae71c0a8110eb21c06b99853c7056b317
+security	7b7e5916aa2f46e57f8bd8cb89c34620ebfda5da
+selinux		f423e5ba76e7e4a6fcb4836b4f072d1fdebba8b5
+lblnet		7e27d6e778cd87b6f2415515d7127eba53fe5d02
+watchdog	a79dcc5bd7ba17c4150430fb7601695ca47133f9
+bdev		feaf3848a813a106f163013af6fcf6c4bfec92d9
+dwmw2-iommu	c3b92c8787367a8bb53d57d9789b558f1295cc96
+iommu		1a51a0ce174ddc0b0c11b6a0dbd179d95020e80b
+osd		724577ca355795b0a25c93ccbeee927871ca1a77
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+nommu		0ce790e7d736cedc563e1fb4e998babf5a4dbc3d
+trivial		98793265b429a3f0b3f1750e74d67cd4d740d162
+audit		def57543418a5f47debae28a0a9dea2effc11692
+pm		72081624d5ad3cf56deb6e727b78c4e7a55e4eec
+apm		b4a133da2eaccb844a7beaef16ffd9c76a0d21d3
+fsnotify	ef9bf3b7144bee6ce1da5616015cabc8771206af
+irda		94d57c4cfaa43e29ca5fa5ff874048cfc67276f5
+edac		4d096ca7e65584dd5845e64c6400f920e694f672
+edac-amd	ed8ccfab5539f930b3b5a954cd4a65414a49baa8
+devicetree	661db794eb8179c7bea02f159bb691a2fff4a8e0
+spi		14c173eb63432ba5d0783b6c4b23a8fe0c76fb0f
+gpio		f408c985cefc9b1d99bc099e1208dd7df3445aa5
+tip		eb5a6fe922fc30685b16f49ada7974f7b10160d9
+rcu		f0312a561912dcab5175e79bab19bdccf931b115
+cputime		c3e0ef9a298e028a82ada28101ccd5cf64d209ee
+uprobes		af1d40ce71bba2622c5fbdbe51c81da605cfc5bd
+cgroup		6b3da11b3c36fdafce3a72e0e90d6c4e99e9aad5
+kmemleak	1502dde87db67a4c1d7f7a1b8361b0c1f1ee6147
+kvm		da69dee073a27ee2d4e50c9b19e9faf8776857eb
+oprofile	42fcb11f001d9912d97e69406ffdfddaa0a944fe
+xen		59e9a6b1ee9fa3992860eb6c48a37b163e97d205
+xen-two		429de5aa7285f14d150cbf716692e0536d489b8a
+xen-pvhvm	b056b6a0144de90707cd22cf7b4f60bf69c86d59
+percpu		6b3da11b3c36fdafce3a72e0e90d6c4e99e9aad5
+workqueues	6b3da11b3c36fdafce3a72e0e90d6c4e99e9aad5
+sfi		5b026c4e3af52fda22c9313a3388344f82f3ba15
+asm-generic	35dbc0e020c6587f78a6c17693beca73aead7b54
+drivers-x86	15b956a0b5651bbb1217ec374fdd67291dabb2af
+hwpoison	46e387bbd82d438b9131e237e6e2cb55a825da49
+sysctl		c2f5631aceb700224d0cfe0465cee18df564a29e
+namespace	7e05c935c50ab5c9ee488c411252076825ec2919
+regmap		0a92815db789bd5a922d882826cf710f9b0b9d85
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+driver-core	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+tty		6b3da11b3c36fdafce3a72e0e90d6c4e99e9aad5
+usb		90a4c0f51e8e44111a926be6f4c87af3938a79c3
+staging		90a4c0f51e8e44111a926be6f4c87af3938a79c3
+char-misc	90a4c0f51e8e44111a926be6f4c87af3938a79c3
+bkl-config	4ba8216cd90560bc402f52076f64d8546e8aefcb
+tmem		805a6af8dba5dfdd35ec35dc52ec0122400b2610
+writeback	bc31b86a5923fad5f3fbb6192f767f410241ba27
+arm-dt		ede338f4ce2fb5ee99d18751df32fbd3b10df268
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		0d2006bbf09e817f125ba1e42b2549bc2c5d7351
+moduleh		6aec187a90aeb883533c9180e2acac1e54c87f7d
+vhost		193a667fba76b3df482cbf865228e26ee246e889
+kmap_atomic	2c2c817038a7e27e2ea297b1c316bf9d96499b52
+xshm		0d0ab68061b4d75d8b3a71f2cc968453dac0d550
+memblock	7bd0b0f0da3b1ec11cbcc798eb0ef747a1184077
+remoteproc	238c1e18edb697596946d10b26cb59d364c5b6e0
+kvmtool		02343793bbaa620439bf9e9abb00b674b4807723
+scsi-post-merge	65112dccf8a113737684366349d7f9ec373ddc47
+akpm		be922c4060dacc37edbff2aa0142d8be6ac7dde2
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 0000000..767b4c5
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,208 @@
+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
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+52xx-and-virtex-current	git	git://git.secretlab.ca/git/linux-2.6#powerpc/merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+scsi-rc-fixes	git	git://bedivere.hansenpartnership.com/git/scsi-rc-fixes-2.6.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.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/jbarnes/pci#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
+cpufreq-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git#fixes
+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-current.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://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git#sh-fixes-for-linus
+rmobile-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git#rmobile-fixes-for-linus
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+spi-current	git	git://git.secretlab.ca/git/linux-2.6#spi/merge
+gpio-current	git	git://git.secretlab.ca/git/linux-2.6#gpio/merge
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-2.6-arm#for-next
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+at91		git	git://github.com/at91linux/linux-2.6-at91.git#at91-next
+davinci		git	git://gitorious.org/linux-davinci/linux-davinci.git#davinci-next
+linux-spec	git	http://git.kernel.org/pub/scm/linux/kernel/git/dwalker/linux-spec#for-next
+omap		git	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git#for-next
+pxa		git	git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git#for-next
+samsung		git	git://git.fluff.org/bjdooks/linux.git#next-samsung
+s5p		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/olof/tegra.git#for-next
+xilinx		git	git://git.xilinx.com/linux-2.6-xlnx.git#arm-next
+blackfin	git	git://git.kernel.org/pub/scm/linux/kernel/git/lliubbo/blackfin.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		quilt	https://www.codeaurora.org/patches/quic/hlk/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
+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
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+4xx		git	git://git.infradead.org/users/jwboyer/powerpc-4xx.git#next
+52xx-and-virtex	git	git://git.secretlab.ca/git/linux-2.6#powerpc/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://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git#sh-latest
+rmobile		git	git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git#rmobile-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://git.kernel.org/pub/scm/linux/kernel/git/czankel/xtensa-next.git#master
+ceph		git	git://github.com/NewDreamNetwork/ceph-client.git#for-next
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#master
+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
+fatfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/hirofumi/fatfs-2.6.git#master
+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
+hfsplus		git	git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus.git#for-next
+jfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git#next
+logfs		git	git://github.com/prasad-joshi/logfs.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
+nilfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/ryusuke/nilfs2.git#for-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#master
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+vfs-scale	git	git://git.kernel.org/pub/scm/linux/kernel/git/npiggin/linux-npiggin.git#vfs-scale-working
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci#linux-next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-i2c/
+bjdooks-i2c	git	git://git.fluff.org/bjdooks/linux.git#next-i2c
+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
+kernel-doc	quilt	http://www.xenotime.net/kernel-doc-patches/current/
+docs		git	git://git.kernel.org/pub/scm/linux/kernel/git/rdunlap/linux-docs.git#docs-move
+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://github.com/jgarzik/libata-dev.git#NEXT
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+acpi		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+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
+scsi		git	git://bedivere.hansenpartnership.com/git/scsi-misc-2.6.git#master
+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
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+async_tx	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-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/padovan/bluetooth-next.git#master
+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
+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
+cpufreq		git	git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git#next
+rr		quilt	http://ozlabs.org/~rusty/kernel/rr-latest/
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://git.kernel.org/pub/scm/linux/kernel/git/rydberg/input-mt.git#next
+lsm		git	git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.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-2.6.git#master
+battery		git	git://git.infradead.org/battery-2.6.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://github.com/jwessel/linux-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-2.6.git#for-next
+hdlc		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux-2.6.git#hdlc-next
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+fbdev		git	git://github.com/schandinat/linux-2.6.git#fbdev-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://gitorious.org/linux-omap-dss2/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.git#linux-next
+bdev		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/bdev.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
+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
+nommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-nommu.git#master
+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-current.git#for-next
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+irda		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git#for-next
+edac		git	git://git.infradead.org/users/mchehab/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
+spi		git	git://git.secretlab.ca/git/linux-2.6#spi/next
+gpio		git	git://git.secretlab.ca/git/linux-2.6#gpio/next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+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
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+kmemleak	git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux.git#kmemleak
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+oprofile	git	git://amd64.org/linux/rric.git#for-next
+xen		git	git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git#upstream/xen
+xen-two		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git#linux-next
+xen-pvhvm	git	git://xenbits.xen.org/people/sstabellini/linux-pvhvm.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
+sfi		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git#sfi-test
+asm-generic	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic#next
+drivers-x86	git	git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86#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
+namespace	git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/linux-2.6-nsfd.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
+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
+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
+bkl-config	git	git://git.kernel.org/pub/scm/linux/kernel/git/arnd/bkl.git#config
+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
+arm-dt		git	git://git.secretlab.ca/git/linux-2.6#devicetree/arm-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
+moduleh		git	git://openlinux.windriver.com/people/paulg/linux-next#for-sfr
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+kmap_atomic	git	git://github.com/congwang/linux.git#kmap_atomic
+xshm		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git#xshm-for-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
+kvmtool		git	git://github.com/penberg/linux-kvm.git#master
+scsi-post-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6.git#master
+akpm		mmotm	http://userweb.kernel.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 0000000..6d66585
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,2639 @@
+$ date
+Fri Jan 20 10:24:37 EST 2012
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at aa303f2 Merge branch 'for-linus/i2c-33' of git://git.fluff.org/bjdooks/linux
+Merging origin/master (dcd6c92 Linux 3.3-rc1)
+$ git merge origin/master
+Updating aa303f2..dcd6c92
+Fast-forward
+ Documentation/acpi/apei/einj.txt                   |   55 +-
+ Documentation/kernel-parameters.txt                |    5 +
+ Documentation/target/tcm_mod_builder.py            |   60 +-
+ Makefile                                           |    4 +-
+ arch/ia64/kernel/acpi.c                            |   10 +-
+ arch/x86/.gitignore                                |    1 +
+ arch/x86/Kconfig                                   |   20 +-
+ arch/x86/include/asm/unistd.h                      |    1 +
+ arch/x86/include/asm/uv/uv_bau.h                   |  107 +-
+ arch/x86/kernel/e820.c                             |    4 +-
+ arch/x86/kernel/tsc.c                              |   14 +-
+ arch/x86/lib/x86-opcode-map.txt                    |    8 +-
+ arch/x86/mm/srat.c                                 |    4 +
+ arch/x86/platform/uv/tlb_uv.c                      |  388 ++-
+ arch/x86/um/shared/sysdep/ptrace.h                 |    5 +
+ drivers/acpi/Makefile                              |    3 +-
+ drivers/acpi/acpica/Makefile                       |  158 +-
+ drivers/acpi/acpica/accommon.h                     |    2 +-
+ drivers/acpi/acpica/acconfig.h                     |    9 +-
+ drivers/acpi/acpica/acdebug.h                      |    2 +-
+ drivers/acpi/acpica/acdispat.h                     |    2 +-
+ drivers/acpi/acpica/acevents.h                     |    3 +-
+ drivers/acpi/acpica/acglobal.h                     |   17 +-
+ drivers/acpi/acpica/achware.h                      |    2 +-
+ drivers/acpi/acpica/acinterp.h                     |    4 +-
+ drivers/acpi/acpica/aclocal.h                      |   26 +-
+ drivers/acpi/acpica/acmacros.h                     |    2 +-
+ drivers/acpi/acpica/acnamesp.h                     |    2 +-
+ drivers/acpi/acpica/acobject.h                     |    8 +-
+ drivers/acpi/acpica/acopcode.h                     |    6 +-
+ drivers/acpi/acpica/acparser.h                     |    2 +-
+ drivers/acpi/acpica/acpredef.h                     |   41 +-
+ drivers/acpi/acpica/acresrc.h                      |  115 +-
+ drivers/acpi/acpica/acstruct.h                     |    2 +-
+ drivers/acpi/acpica/actables.h                     |    2 +-
+ drivers/acpi/acpica/acutils.h                      |   21 +-
+ drivers/acpi/acpica/amlcode.h                      |   29 +-
+ drivers/acpi/acpica/amlresrc.h                     |  138 +-
+ drivers/acpi/acpica/dsargs.c                       |   18 +-
+ drivers/acpi/acpica/dscontrol.c                    |    2 +-
+ drivers/acpi/acpica/dsfield.c                      |   83 +-
+ drivers/acpi/acpica/dsinit.c                       |    2 +-
+ drivers/acpi/acpica/dsmethod.c                     |    2 +-
+ drivers/acpi/acpica/dsmthdat.c                     |    2 +-
+ drivers/acpi/acpica/dsobject.c                     |    2 +-
+ drivers/acpi/acpica/dsopcode.c                     |    2 +-
+ drivers/acpi/acpica/dsutils.c                      |    2 +-
+ drivers/acpi/acpica/dswexec.c                      |    2 +-
+ drivers/acpi/acpica/dswload.c                      |    2 +-
+ drivers/acpi/acpica/dswload2.c                     |    2 +-
+ drivers/acpi/acpica/dswscope.c                     |    2 +-
+ drivers/acpi/acpica/dswstate.c                     |    2 +-
+ drivers/acpi/acpica/evevent.c                      |   14 +-
+ drivers/acpi/acpica/evglock.c                      |    8 +-
+ drivers/acpi/acpica/evgpe.c                        |    2 +-
+ drivers/acpi/acpica/evgpeblk.c                     |    2 +-
+ drivers/acpi/acpica/evgpeinit.c                    |    2 +-
+ drivers/acpi/acpica/evgpeutil.c                    |    2 +-
+ drivers/acpi/acpica/evmisc.c                       |    2 +-
+ drivers/acpi/acpica/evregion.c                     |   31 +-
+ drivers/acpi/acpica/evrgnini.c                     |    2 +-
+ drivers/acpi/acpica/evsci.c                        |    2 +-
+ drivers/acpi/acpica/evxface.c                      |    2 +-
+ drivers/acpi/acpica/evxfevnt.c                     |    2 +-
+ drivers/acpi/acpica/evxfgpe.c                      |    2 +-
+ drivers/acpi/acpica/evxfregn.c                     |    2 +-
+ drivers/acpi/acpica/exconfig.c                     |    8 +-
+ drivers/acpi/acpica/exconvrt.c                     |    2 +-
+ drivers/acpi/acpica/excreate.c                     |   31 +-
+ drivers/acpi/acpica/exdebug.c                      |    2 +-
+ drivers/acpi/acpica/exdump.c                       |    9 +-
+ drivers/acpi/acpica/exfield.c                      |   30 +-
+ drivers/acpi/acpica/exfldio.c                      |   38 +-
+ drivers/acpi/acpica/exmisc.c                       |    2 +-
+ drivers/acpi/acpica/exmutex.c                      |    2 +-
+ drivers/acpi/acpica/exnames.c                      |    2 +-
+ drivers/acpi/acpica/exoparg1.c                     |    2 +-
+ drivers/acpi/acpica/exoparg2.c                     |    2 +-
+ drivers/acpi/acpica/exoparg3.c                     |    2 +-
+ drivers/acpi/acpica/exoparg6.c                     |    2 +-
+ drivers/acpi/acpica/exprep.c                       |   27 +-
+ drivers/acpi/acpica/exregion.c                     |    2 +-
+ drivers/acpi/acpica/exresnte.c                     |    2 +-
+ drivers/acpi/acpica/exresolv.c                     |    2 +-
+ drivers/acpi/acpica/exresop.c                      |    2 +-
+ drivers/acpi/acpica/exstore.c                      |    2 +-
+ drivers/acpi/acpica/exstoren.c                     |    2 +-
+ drivers/acpi/acpica/exstorob.c                     |    2 +-
+ drivers/acpi/acpica/exsystem.c                     |    2 +-
+ drivers/acpi/acpica/exutils.c                      |   27 +-
+ drivers/acpi/acpica/hwacpi.c                       |    2 +-
+ drivers/acpi/acpica/hwgpe.c                        |    2 +-
+ drivers/acpi/acpica/hwpci.c                        |    2 +-
+ drivers/acpi/acpica/hwregs.c                       |    2 +-
+ drivers/acpi/acpica/hwsleep.c                      |    2 +-
+ drivers/acpi/acpica/hwtimer.c                      |    2 +-
+ drivers/acpi/acpica/hwvalid.c                      |    4 +-
+ drivers/acpi/acpica/hwxface.c                      |    2 +-
+ drivers/acpi/acpica/nsaccess.c                     |    2 +-
+ drivers/acpi/acpica/nsalloc.c                      |    2 +-
+ drivers/acpi/acpica/nsdump.c                       |    2 +-
+ drivers/acpi/acpica/nsdumpdv.c                     |    2 +-
+ drivers/acpi/acpica/nseval.c                       |    2 +-
+ drivers/acpi/acpica/nsinit.c                       |    2 +-
+ drivers/acpi/acpica/nsload.c                       |    2 +-
+ drivers/acpi/acpica/nsnames.c                      |    2 +-
+ drivers/acpi/acpica/nsobject.c                     |    2 +-
+ drivers/acpi/acpica/nsparse.c                      |    2 +-
+ drivers/acpi/acpica/nspredef.c                     |   31 +-
+ drivers/acpi/acpica/nsrepair.c                     |    3 +-
+ drivers/acpi/acpica/nsrepair2.c                    |    7 +-
+ drivers/acpi/acpica/nssearch.c                     |    2 +-
+ drivers/acpi/acpica/nsutils.c                      |    2 +-
+ drivers/acpi/acpica/nswalk.c                       |    2 +-
+ drivers/acpi/acpica/nsxfeval.c                     |    2 +-
+ drivers/acpi/acpica/nsxfname.c                     |    2 +-
+ drivers/acpi/acpica/nsxfobj.c                      |    2 +-
+ drivers/acpi/acpica/psargs.c                       |  143 +-
+ drivers/acpi/acpica/psloop.c                       |    2 +-
+ drivers/acpi/acpica/psopcode.c                     |   15 +-
+ drivers/acpi/acpica/psparse.c                      |    2 +-
+ drivers/acpi/acpica/psscope.c                      |    2 +-
+ drivers/acpi/acpica/pstree.c                       |    8 +-
+ drivers/acpi/acpica/psutils.c                      |    2 +-
+ drivers/acpi/acpica/pswalk.c                       |    2 +-
+ drivers/acpi/acpica/psxface.c                      |    2 +-
+ drivers/acpi/acpica/rsaddr.c                       |    2 +-
+ drivers/acpi/acpica/rscalc.c                       |   89 +-
+ drivers/acpi/acpica/rscreate.c                     |   69 +-
+ drivers/acpi/acpica/rsdump.c                       |  196 +-
+ drivers/acpi/acpica/rsinfo.c                       |   58 +-
+ drivers/acpi/acpica/rsio.c                         |    2 +-
+ drivers/acpi/acpica/rsirq.c                        |   33 +-
+ drivers/acpi/acpica/rslist.c                       |   77 +-
+ drivers/acpi/acpica/rsmemory.c                     |    2 +-
+ drivers/acpi/acpica/rsmisc.c                       |  269 ++-
+ drivers/acpi/acpica/rsserial.c                     |  441 +++
+ drivers/acpi/acpica/rsutils.c                      |   56 +-
+ drivers/acpi/acpica/rsxface.c                      |   52 +-
+ drivers/acpi/acpica/tbfadt.c                       |   41 +-
+ drivers/acpi/acpica/tbfind.c                       |    2 +-
+ drivers/acpi/acpica/tbinstal.c                     |    2 +-
+ drivers/acpi/acpica/tbutils.c                      |    9 +-
+ drivers/acpi/acpica/tbxface.c                      |    2 +-
+ drivers/acpi/acpica/tbxfroot.c                     |    2 +-
+ drivers/acpi/acpica/utaddress.c                    |  294 ++
+ drivers/acpi/acpica/utalloc.c                      |    2 +-
+ drivers/acpi/acpica/utcopy.c                       |    2 +-
+ drivers/acpi/acpica/utdebug.c                      |    2 +-
+ drivers/acpi/acpica/utdecode.c                     |    6 +-
+ drivers/acpi/acpica/utdelete.c                     |   15 +-
+ drivers/acpi/acpica/uteval.c                       |    2 +-
+ drivers/acpi/acpica/utglobal.c                     |    8 +-
+ drivers/acpi/acpica/utids.c                        |    2 +-
+ drivers/acpi/acpica/utinit.c                       |    3 +-
+ drivers/acpi/acpica/utlock.c                       |    2 +-
+ drivers/acpi/acpica/utmath.c                       |    2 +-
+ drivers/acpi/acpica/utmisc.c                       |    2 +-
+ drivers/acpi/acpica/utmutex.c                      |   11 +-
+ drivers/acpi/acpica/utobject.c                     |    2 +-
+ drivers/acpi/acpica/utosi.c                        |    2 +-
+ drivers/acpi/acpica/utresrc.c                      |  278 ++-
+ drivers/acpi/acpica/utstate.c                      |    2 +-
+ drivers/acpi/acpica/utxface.c                      |   40 +-
+ drivers/acpi/acpica/utxferror.c                    |    2 +-
+ drivers/acpi/acpica/utxfmutex.c                    |  187 +
+ drivers/acpi/apei/apei-base.c                      |  150 +-
+ drivers/acpi/apei/apei-internal.h                  |    6 +
+ drivers/acpi/apei/einj.c                           |  290 ++-
+ drivers/acpi/apei/erst.c                           |    5 +-
+ drivers/acpi/apei/ghes.c                           |  102 +-
+ drivers/acpi/apei/hest.c                           |    5 +-
+ drivers/acpi/atomicio.c                            |   77 +-
+ drivers/acpi/numa.c                                |    6 +
+ drivers/acpi/nvs.c                                 |   53 +-
+ drivers/acpi/osl.c                                 |  242 +-
+ drivers/acpi/processor_core.c                      |   26 +-
+ drivers/acpi/processor_driver.c                    |   20 +-
+ drivers/block/nvme.c                               |    8 +-
+ drivers/char/tpm/tpm.c                             |    9 +
+ drivers/char/tpm/tpm.h                             |    3 +
+ drivers/gpio/Kconfig                               |    1 +
+ drivers/gpio/gpio-ml-ioh.c                         |    8 +-
+ drivers/gpio/gpio-pch.c                            |    4 +-
+ drivers/gpio/gpio-tps65910.c                       |    2 +-
+ drivers/idle/intel_idle.c                          |   96 +-
+ drivers/infiniband/Kconfig                         |    1 +
+ drivers/infiniband/Makefile                        |    1 +
+ drivers/infiniband/ulp/srpt/Kconfig                |   12 +
+ drivers/infiniband/ulp/srpt/Makefile               |    2 +
+ drivers/infiniband/ulp/srpt/ib_dm_mad.h            |  139 +
+ drivers/infiniband/ulp/srpt/ib_srpt.c              | 4073 ++++++++++++++++++++
+ drivers/infiniband/ulp/srpt/ib_srpt.h              |  444 +++
+ drivers/target/iscsi/iscsi_target.c                |   19 +-
+ drivers/target/iscsi/iscsi_target_auth.c           |   36 +-
+ drivers/target/iscsi/iscsi_target_configfs.c       |   11 +-
+ drivers/target/iscsi/iscsi_target_device.c         |    3 +-
+ drivers/target/iscsi/iscsi_target_erl0.c           |    2 +-
+ drivers/target/iscsi/iscsi_target_erl1.c           |    2 +-
+ drivers/target/iscsi/iscsi_target_erl2.c           |    2 +-
+ drivers/target/iscsi/iscsi_target_login.c          |   23 +-
+ drivers/target/iscsi/iscsi_target_nego.c           |    4 +-
+ drivers/target/iscsi/iscsi_target_nodeattrib.c     |    3 +-
+ drivers/target/iscsi/iscsi_target_stat.c           |   17 +-
+ drivers/target/iscsi/iscsi_target_tmr.c            |    2 +-
+ drivers/target/iscsi/iscsi_target_tpg.c            |    6 +-
+ drivers/target/iscsi/iscsi_target_util.c           |    8 +-
+ drivers/target/loopback/tcm_loop.c                 |   33 +-
+ drivers/target/loopback/tcm_loop.h                 |   11 +-
+ drivers/target/target_core_alua.c                  |    7 +-
+ drivers/target/target_core_cdb.c                   |   39 +-
+ drivers/target/target_core_cdb.h                   |   14 -
+ drivers/target/target_core_configfs.c              |   34 +-
+ drivers/target/target_core_device.c                |   15 +-
+ drivers/target/target_core_fabric_configfs.c       |    8 +-
+ drivers/target/target_core_fabric_lib.c            |   13 +-
+ drivers/target/target_core_file.c                  |   15 +-
+ drivers/target/target_core_hba.c                   |    7 +-
+ drivers/target/target_core_hba.h                   |    7 -
+ drivers/target/target_core_iblock.c                |    7 +-
+ drivers/target/target_core_internal.h              |  123 +
+ drivers/target/target_core_pr.c                    |   24 +-
+ drivers/target/target_core_pr.h                    |    2 -
+ drivers/target/target_core_pscsi.c                 |   20 +-
+ drivers/target/target_core_rd.c                    |    6 +-
+ drivers/target/target_core_stat.c                  |    9 +-
+ drivers/target/target_core_stat.h                  |    8 -
+ drivers/target/target_core_tmr.c                   |   36 +-
+ drivers/target/target_core_tpg.c                   |    9 +-
+ drivers/target/target_core_transport.c             |  343 +-
+ drivers/target/target_core_ua.c                    |    6 +-
+ drivers/target/tcm_fc/tfc_cmd.c                    |   57 +-
+ drivers/target/tcm_fc/tfc_conf.c                   |    6 +-
+ drivers/target/tcm_fc/tfc_io.c                     |    5 +-
+ drivers/target/tcm_fc/tfc_sess.c                   |    5 +-
+ drivers/xen/biomerge.c                             |    1 +
+ fs/inode.c                                         |    3 -
+ fs/proc/stat.c                                     |    2 +
+ fs/qnx4/inode.c                                    |   62 +-
+ fs/super.c                                         |    2 +
+ include/acpi/acnames.h                             |    1 +
+ include/acpi/acpi_numa.h                           |    1 +
+ include/acpi/acpiosxf.h                            |    7 -
+ include/acpi/acpixf.h                              |   32 +-
+ include/acpi/acrestyp.h                            |  207 +-
+ include/acpi/actbl.h                               |   23 +-
+ include/acpi/actbl1.h                              |   57 +-
+ include/acpi/actbl3.h                              |  552 +++
+ include/acpi/actypes.h                             |   12 +-
+ include/linux/acpi.h                               |   20 +-
+ include/linux/acpi_io.h                            |    3 +
+ include/linux/cpuidle.h                            |    7 +
+ include/linux/key.h                                |    2 +-
+ include/target/target_core_backend.h               |   65 +
+ include/target/target_core_base.h                  |  169 +-
+ include/target/target_core_device.h                |   63 -
+ ...rget_core_fabric_ops.h => target_core_fabric.h} |   94 +-
+ include/target/target_core_fabric_lib.h            |   28 -
+ include/target/target_core_tmr.h                   |   35 -
+ include/target/target_core_tpg.h                   |   35 -
+ include/target/target_core_transport.h             |  287 --
+ kernel/tracepoint.c                                |    7 +-
+ lib/mpi/mpicoder.c                                 |    2 +
+ security/integrity/ima/ima_policy.c                |    3 +-
+ security/keys/user_defined.c                       |    6 +-
+ tools/power/x86/turbostat/turbostat.c              |    2 +
+ 266 files changed, 10833 insertions(+), 1974 deletions(-)
+ create mode 100644 drivers/acpi/acpica/rsserial.c
+ create mode 100644 drivers/acpi/acpica/utaddress.c
+ create mode 100644 drivers/acpi/acpica/utxfmutex.c
+ create mode 100644 drivers/infiniband/ulp/srpt/Kconfig
+ create mode 100644 drivers/infiniband/ulp/srpt/Makefile
+ create mode 100644 drivers/infiniband/ulp/srpt/ib_dm_mad.h
+ create mode 100644 drivers/infiniband/ulp/srpt/ib_srpt.c
+ create mode 100644 drivers/infiniband/ulp/srpt/ib_srpt.h
+ delete mode 100644 drivers/target/target_core_cdb.h
+ delete mode 100644 drivers/target/target_core_hba.h
+ create mode 100644 drivers/target/target_core_internal.h
+ delete mode 100644 drivers/target/target_core_stat.h
+ create mode 100644 include/acpi/actbl3.h
+ create mode 100644 include/target/target_core_backend.h
+ delete mode 100644 include/target/target_core_device.h
+ rename include/target/{target_core_fabric_ops.h => target_core_fabric.h} (50%)
+ delete mode 100644 include/target/target_core_fabric_lib.h
+ delete mode 100644 include/target/target_core_tmr.h
+ delete mode 100644 include/target/target_core_tpg.h
+ delete mode 100644 include/target/target_core_transport.h
+Merging fixes/master (371de6e drm/i915: Disable RC6 on Sandybridge by default)
+$ git merge fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (fa0ad65 kconfig: adapt update-po-config to new UML layout)
+$ git merge kbuild-current/rc-fixes
+Already up-to-date.
+Merging arm-current/fixes (f1cfd9e ARM: fix a section mismatch warning with our use of memblock)
+$ git merge arm-current/fixes
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                  |    2 +-
+ arch/arm/mach-pxa/devices.c       |   20 ---
+ arch/arm/mach-pxa/pxa25x.c        |    2 -
+ arch/arm/mach-pxa/pxa27x.c        |    2 -
+ arch/arm/mach-pxa/pxa300.c        |    1 -
+ arch/arm/mach-pxa/pxa320.c        |    1 -
+ arch/arm/mach-pxa/pxa3xx.c        |    1 -
+ arch/arm/mach-pxa/pxa95x.c        |    1 -
+ arch/arm/mach-sa1100/clock.c      |   91 +++--------
+ arch/arm/mach-sa1100/collie.c     |    5 +-
+ arch/arm/mach-sa1100/cpu-sa1100.c |    2 +-
+ arch/arm/mach-sa1100/generic.c    |   20 ---
+ arch/arm/mm/init.c                |    2 +-
+ drivers/rtc/Kconfig               |    2 +-
+ drivers/rtc/rtc-sa1100.c          |  295 ++++++++++++++-----------------------
+ 15 files changed, 144 insertions(+), 303 deletions(-)
+Merging m68k-current/for-linus (3bd9e50 m68k/mac: Make CONFIG_HEARTBEAT unavailable on Mac)
+$ git merge m68k-current/for-linus
+Already up-to-date.
+Merging powerpc-merge/merge (ebb7f61 powerpc: Fix unpaired __trace_hcall_entry and __trace_hcall_exit)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging 52xx-and-virtex-current/powerpc/merge (c49f878 dtc/powerpc: remove obsolete .gitignore entries)
+$ git merge 52xx-and-virtex-current/powerpc/merge
+Already up-to-date.
+Merging sparc/master (e51e07e sparc32: forced setting of mode of sun4m per-cpu timers)
+$ git merge sparc/master
+Merge made by the 'recursive' strategy.
+ arch/sparc/kernel/sun4m_irq.c |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+Merging scsi-rc-fixes/master (6f6c2aa [SCSI] fcoe: fix fcoe in a DCB environment by adding DCB notifiers to set skb priority)
+$ git merge scsi-rc-fixes/master
+Already up-to-date.
+Merging net/master (3d8fe98 ixgbevf: make operations tables const)
+$ git merge net/master
+Merge made by the 'recursive' strategy.
+ arch/x86/net/bpf_jit_comp.c                        |   36 +++++---
+ drivers/net/bonding/bond_alb.c                     |   27 ++----
+ drivers/net/ethernet/cisco/enic/enic.h             |    2 +-
+ drivers/net/ethernet/cisco/enic/enic_main.c        |   40 +++++----
+ drivers/net/ethernet/faraday/ftgmac100.c           |    1 +
+ drivers/net/ethernet/faraday/ftmac100.c            |    1 +
+ drivers/net/ethernet/intel/igb/Makefile            |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.c       |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.h       |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_defines.h     |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_hw.h          |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_mac.c         |    4 +-
+ drivers/net/ethernet/intel/igb/e1000_mac.h         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_mbx.c         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_mbx.h         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_nvm.c         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_nvm.h         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.c         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.h         |    2 +-
+ drivers/net/ethernet/intel/igb/e1000_regs.h        |    2 +-
+ drivers/net/ethernet/intel/igb/igb.h               |    2 +-
+ drivers/net/ethernet/intel/igb/igb_ethtool.c       |    2 +-
+ drivers/net/ethernet/intel/igb/igb_main.c          |   10 +-
+ drivers/net/ethernet/intel/igbvf/ethtool.c         |    3 +-
+ drivers/net/ethernet/intel/igbvf/netdev.c          |    5 -
+ drivers/net/ethernet/intel/ixgbe/ixgbe_type.h      |   32 ++++----
+ drivers/net/ethernet/intel/ixgbevf/ethtool.c       |    5 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h       |    8 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |   41 +++++----
+ drivers/net/ethernet/intel/ixgbevf/mbx.c           |    3 +-
+ drivers/net/ethernet/intel/ixgbevf/vf.c            |    7 +-
+ drivers/net/ethernet/intel/ixgbevf/vf.h            |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/en_ethtool.c    |   93 ++++++++++++++++++++
+ drivers/net/ethernet/mellanox/mlx4/en_main.c       |    6 +-
+ drivers/net/ethernet/mellanox/mlx4/en_rx.c         |    8 ++-
+ drivers/net/ethernet/mellanox/mlx4/mlx4_en.h       |    2 +-
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |   17 +++-
+ drivers/net/wireless/b43/Kconfig                   |    6 ++
+ drivers/net/wireless/b43/main.c                    |    2 +
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     |   10 ++-
+ net/ipv6/addrconf.c                                |   61 +++++++++-----
+ net/mac80211/debugfs_key.c                         |    7 +-
+ net/mac80211/mesh_hwmp.c                           |    8 +-
+ net/mac80211/mesh_plink.c                          |    4 +-
+ net/mac80211/mlme.c                                |   38 ++++++---
+ 45 files changed, 342 insertions(+), 177 deletions(-)
+Merging sound-current/for-linus (f0e48b6 ALSA: virtuoso: Xonar DS: fix polarity of front output)
+$ git merge sound-current/for-linus
+Already up-to-date.
+Merging pci-current/for-linus (8b6a5af PCI: Add Thinkpad SL510 to pci=nocrs blacklist)
+$ git merge pci-current/for-linus
+Already up-to-date.
+Merging wireless/master (4f3d09d b43: add option to avoid duplicating device support with brcmsmac)
+$ git merge wireless/master
+Already up-to-date.
+Merging driver-core.current/driver-core-linus (90a4c0f uml: fix compile for x86-64)
+$ git merge driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (6b3da11 Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu)
+$ git merge tty.current/tty-linus
+Already up-to-date.
+Merging usb.current/usb-linus (90a4c0f uml: fix compile for x86-64)
+$ git merge usb.current/usb-linus
+Already up-to-date.
+Merging staging.current/staging-linus (90a4c0f uml: fix compile for x86-64)
+$ git merge staging.current/staging-linus
+Already up-to-date.
+Merging char-misc.current/char-misc-linus (90a4c0f uml: fix compile for x86-64)
+$ git merge char-misc.current/char-misc-linus
+Already up-to-date.
+Merging cpufreq-current/fixes (5983fe2 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge cpufreq-current/fixes
+Already up-to-date.
+Merging input-current/for-linus (52965cc Input: bcm5974 - set BUTTONPAD property)
+$ git merge input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (307729c md/raid1: perform bad-block tests for WriteMostly devices too.)
+$ git merge md-current/for-linus
+Already up-to-date.
+Merging audit-current/for-linus (def5754 Audit: remove spaces from audit_log_d_path)
+$ git merge audit-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (51fc6dc crypto: sha512 - reduce stack usage to safe number)
+$ git merge crypto-current/master
+Merge made by the 'recursive' strategy.
+ crypto/sha512_generic.c |   62 +++++++++++++++++++++++++---------------------
+ 1 files changed, 34 insertions(+), 28 deletions(-)
+Merging ide/master (0ab3d8b cy82c693: fix PCI device selection)
+$ git merge ide/master
+Already up-to-date.
+Merging dwmw2/master (244dc4e Merge git://git.infradead.org/users/dwmw2/random-2.6)
+$ git merge dwmw2/master
+Already up-to-date.
+Merging sh-current/sh-fixes-for-linus (21d41f2 sh: fix the compile error in setup-sh7757.c)
+$ git merge sh-current/sh-fixes-for-linus
+Already up-to-date.
+Merging rmobile-current/rmobile-fixes-for-linus (a408bae ARM: mach-shmobile: sh7372 CMT3 and CMT4 clock support)
+$ git merge rmobile-current/rmobile-fixes-for-linus
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (c89810a ARM: prom.h: Fix build error by removing unneeded header file)
+$ git merge devicetree-current/devicetree/merge
+Already up-to-date.
+Merging spi-current/spi/merge (e583685 Merge branch 'spi/next' (early part) into spi/merge)
+$ git merge spi-current/spi/merge
+Already up-to-date.
+Merging gpio-current/gpio/merge (94bd244 gpio: tps65910: Use correct offset for gpio initialization)
+$ git merge gpio-current/gpio/merge
+Already up-to-date.
+Merging arm/for-next (33710e3 Merge branches 'fixes' and 'restart' into for-next)
+$ git merge arm/for-next
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-gemini/include/mach/system.h   |    1 +
+ arch/arm/mach-shmobile/include/mach/system.h |    1 +
+ arch/arm/mach-vt8500/include/mach/system.h   |    1 +
+ 3 files changed, 3 insertions(+), 0 deletions(-)
+Merging arm-soc/for-next (0db991d LOCAL: add back arch/arm/arm-soc-for-next-contents.txt)
+$ git merge arm-soc/for-next
+Resolved 'arch/arm/mach-s3c64xx/mach-crag6410.c' using previous resolution.
+Resolved 'drivers/dma/pl330.c' using previous resolution.
+Resolved 'drivers/media/common/tuners/tda18218.c' using previous resolution.
+Resolved 'drivers/media/video/omap3isp/ispccdc.c' using previous resolution.
+Auto-merging drivers/rtc/rtc-s3c.c
+Auto-merging drivers/media/video/omap3isp/ispccdc.c
+CONFLICT (content): Merge conflict in drivers/media/video/omap3isp/ispccdc.c
+Auto-merging drivers/media/common/tuners/tda18218.c
+CONFLICT (content): Merge conflict in drivers/media/common/tuners/tda18218.c
+Auto-merging drivers/dma/pl330.c
+CONFLICT (content): Merge conflict in drivers/dma/pl330.c
+Auto-merging drivers/dma/Kconfig
+Auto-merging arch/arm/plat-samsung/devs.c
+Auto-merging arch/arm/mach-s3c64xx/mach-crag6410.c
+CONFLICT (content): Merge conflict in arch/arm/mach-s3c64xx/mach-crag6410.c
+Auto-merging arch/arm/mach-s3c64xx/Kconfig
+Auto-merging arch/arm/mach-s3c2443/s3c2443.c
+Auto-merging arch/arm/mach-s3c2416/s3c2416.c
+Removing arch/arm/mach-mx5/pm-imx5.c
+Removing arch/arm/mach-mx5/Makefile.boot
+Removing arch/arm/mach-mx5/Makefile
+Removing arch/arm/mach-mx5/Kconfig
+Auto-merging arch/arm/mach-imx/pm-imx5.c
+Auto-merging arch/arm/mach-imx/mach-mx53_smd.c
+Auto-merging arch/arm/mach-imx/mach-mx53_loco.c
+Auto-merging arch/arm/mach-imx/mach-mx53_evk.c
+Auto-merging arch/arm/mach-imx/mach-mx53_ard.c
+Auto-merging arch/arm/mach-imx/clock-mx51-mx53.c
+Auto-merging arch/arm/mach-exynos/mach-origen.c
+Auto-merging arch/arm/mach-exynos/common.c
+Removing arch/arm/configs/mx3_defconfig
+Auto-merging arch/arm/configs/imx_v6_v7_defconfig
+Removing arch/arm/common/pl330.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 0dfe8ac] Merge remote-tracking branch 'arm-soc/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/Makefile                                  |    1 -
+ arch/arm/arm-soc-for-next-contents.txt             |  115 ++
+ arch/arm/common/Kconfig                            |    3 -
+ arch/arm/common/Makefile                           |    1 -
+ arch/arm/common/pl330.c                            | 1959 --------------------
+ .../configs/{mx5_defconfig => imx_v6_v7_defconfig} |   61 +-
+ arch/arm/configs/mx3_defconfig                     |  144 --
+ arch/arm/include/asm/hardware/pl330.h              |  338 ++--
+ arch/arm/mach-at91/at91sam9263_devices.c           |   13 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |  113 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |    8 +-
+ arch/arm/mach-at91/board-sam9m10g45ek.c            |   80 +-
+ arch/arm/mach-at91/include/mach/board.h            |    6 +-
+ arch/arm/mach-exynos/Kconfig                       |    3 +
+ arch/arm/mach-exynos/clock.c                       |    9 +
+ arch/arm/mach-exynos/common.c                      |    7 +-
+ arch/arm/mach-exynos/dma.c                         |  130 ++-
+ arch/arm/mach-exynos/include/mach/irqs.h           |    2 +
+ arch/arm/mach-exynos/include/mach/map.h            |    7 +-
+ arch/arm/mach-exynos/include/mach/regs-clock.h     |   42 +
+ arch/arm/mach-exynos/mach-nuri.c                   |   12 +-
+ arch/arm/mach-exynos/mach-origen.c                 |   35 +
+ arch/arm/mach-exynos/mach-universal_c210.c         |    1 +
+ arch/arm/mach-imx/Kconfig                          |  239 +++
+ arch/arm/mach-imx/Makefile                         |   22 +
+ arch/arm/mach-imx/Makefile.boot                    |   12 +
+ arch/arm/{mach-mx5 => mach-imx}/clock-mx51-mx53.c  |    2 +-
+ arch/arm/{mach-mx5/cpu.c => mach-imx/cpu-imx5.c}   |    0
+ arch/arm/{mach-mx5 => mach-imx}/cpu_op-mx51.c      |    0
+ arch/arm/{mach-mx5 => mach-imx}/cpu_op-mx51.h      |    0
+ .../crm_regs.h => mach-imx/crm-regs-imx5.h}        |    0
+ arch/arm/{mach-mx5 => mach-imx}/devices-imx50.h    |    0
+ arch/arm/{mach-mx5 => mach-imx}/devices-imx51.h    |    0
+ arch/arm/{mach-mx5 => mach-imx}/devices-imx53.h    |    0
+ arch/arm/{mach-mx5 => mach-imx}/efika.h            |    0
+ arch/arm/{mach-mx5/ehci.c => mach-imx/ehci-imx5.c} |    0
+ .../eukrea_mbimx51-baseboard.c                     |    0
+ .../eukrea_mbimxsd-baseboard.c                     |    0
+ arch/arm/{mach-mx5 => mach-imx}/imx51-dt.c         |    0
+ arch/arm/{mach-mx5 => mach-imx}/imx53-dt.c         |    0
+ .../board-cpuimx51.c => mach-imx/mach-cpuimx51.c}  |    0
+ .../mach-cpuimx51sd.c}                             |    0
+ .../board-mx50_rdp.c => mach-imx/mach-mx50_rdp.c}  |    0
+ .../board-mx51_3ds.c => mach-imx/mach-mx51_3ds.c}  |    0
+ .../mach-mx51_babbage.c}                           |    0
+ .../mach-mx51_efikamx.c}                           |    0
+ .../mach-mx51_efikasb.c}                           |    0
+ .../board-mx53_ard.c => mach-imx/mach-mx53_ard.c}  |    1 -
+ .../board-mx53_evk.c => mach-imx/mach-mx53_evk.c}  |    1 -
+ .../mach-mx53_loco.c}                              |    1 -
+ .../board-mx53_smd.c => mach-imx/mach-mx53_smd.c}  |    1 -
+ arch/arm/{mach-mx5/mm.c => mach-imx/mm-imx5.c}     |    0
+ arch/arm/{mach-mx5 => mach-imx}/mx51_efika.c       |    0
+ arch/arm/{mach-mx5/system.c => mach-imx/pm-imx5.c} |   89 +-
+ arch/arm/mach-mx5/Kconfig                          |  244 ---
+ arch/arm/mach-mx5/Makefile                         |   26 -
+ arch/arm/mach-mx5/Makefile.boot                    |    9 -
+ arch/arm/mach-mx5/pm-imx5.c                        |   83 -
+ arch/arm/mach-s3c2416/s3c2416.c                    |    2 +
+ arch/arm/mach-s3c2443/s3c2443.c                    |    2 +
+ arch/arm/mach-s3c64xx/Kconfig                      |    1 +
+ arch/arm/mach-s3c64xx/Makefile                     |    1 +
+ arch/arm/mach-s3c64xx/clock.c                      |   20 +-
+ arch/arm/mach-s3c64xx/cpuidle.c                    |   91 +
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |   55 +
+ arch/arm/plat-mxc/Kconfig                          |   15 +-
+ arch/arm/plat-s5p/Kconfig                          |    5 +
+ arch/arm/plat-samsung/dev-backlight.c              |    2 +
+ arch/arm/plat-samsung/devs.c                       |   28 +
+ arch/arm/plat-samsung/include/plat/devs.h          |    1 +
+ arch/arm/plat-samsung/include/plat/dma-pl330.h     |   16 +
+ arch/arm/plat-samsung/include/plat/regs-rtc.h      |   81 +-
+ arch/arm/plat-samsung/include/plat/rtc-core.h      |   27 +
+ drivers/dma/Kconfig                                |    1 -
+ drivers/dma/pl330.c                                | 1854 ++++++++++++++++++-
+ drivers/media/video/omap3isp/ispccdc.c             |    2 +-
+ drivers/rtc/rtc-s3c.c                              |   71 +-
+ 77 files changed, 3321 insertions(+), 2774 deletions(-)
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ delete mode 100644 arch/arm/common/pl330.c
+ rename arch/arm/configs/{mx5_defconfig => imx_v6_v7_defconfig} (80%)
+ delete mode 100644 arch/arm/configs/mx3_defconfig
+ rename arch/arm/{mach-mx5 => mach-imx}/clock-mx51-mx53.c (99%)
+ rename arch/arm/{mach-mx5/cpu.c => mach-imx/cpu-imx5.c} (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/cpu_op-mx51.c (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/cpu_op-mx51.h (100%)
+ rename arch/arm/{mach-mx5/crm_regs.h => mach-imx/crm-regs-imx5.h} (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/devices-imx50.h (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/devices-imx51.h (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/devices-imx53.h (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/efika.h (100%)
+ rename arch/arm/{mach-mx5/ehci.c => mach-imx/ehci-imx5.c} (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/eukrea_mbimx51-baseboard.c (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/eukrea_mbimxsd-baseboard.c (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/imx51-dt.c (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/imx53-dt.c (100%)
+ rename arch/arm/{mach-mx5/board-cpuimx51.c => mach-imx/mach-cpuimx51.c} (100%)
+ rename arch/arm/{mach-mx5/board-cpuimx51sd.c => mach-imx/mach-cpuimx51sd.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx50_rdp.c => mach-imx/mach-mx50_rdp.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx51_3ds.c => mach-imx/mach-mx51_3ds.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx51_babbage.c => mach-imx/mach-mx51_babbage.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx51_efikamx.c => mach-imx/mach-mx51_efikamx.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx51_efikasb.c => mach-imx/mach-mx51_efikasb.c} (100%)
+ rename arch/arm/{mach-mx5/board-mx53_ard.c => mach-imx/mach-mx53_ard.c} (99%)
+ rename arch/arm/{mach-mx5/board-mx53_evk.c => mach-imx/mach-mx53_evk.c} (99%)
+ rename arch/arm/{mach-mx5/board-mx53_loco.c => mach-imx/mach-mx53_loco.c} (99%)
+ rename arch/arm/{mach-mx5/board-mx53_smd.c => mach-imx/mach-mx53_smd.c} (99%)
+ rename arch/arm/{mach-mx5/mm.c => mach-imx/mm-imx5.c} (100%)
+ rename arch/arm/{mach-mx5 => mach-imx}/mx51_efika.c (100%)
+ rename arch/arm/{mach-mx5/system.c => mach-imx/pm-imx5.c} (58%)
+ delete mode 100644 arch/arm/mach-mx5/Kconfig
+ delete mode 100644 arch/arm/mach-mx5/Makefile
+ delete mode 100644 arch/arm/mach-mx5/Makefile.boot
+ delete mode 100644 arch/arm/mach-mx5/pm-imx5.c
+ create mode 100644 arch/arm/mach-s3c64xx/cpuidle.c
+ create mode 100644 arch/arm/plat-samsung/include/plat/rtc-core.h
+Merging arm-perf/for-next/perf (7e9523f ARM: perf: remove unused armpmu_get_max_events)
+$ git merge arm-perf/for-next/perf
+Merge made by the 'recursive' strategy.
+Merging at91/at91-next (8748dfa Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux)
+$ git merge at91/at91-next
+Already up-to-date.
+Merging davinci/davinci-next (fe0d422 Linux 3.0-rc6)
+$ git merge davinci/davinci-next
+Already up-to-date.
+Merging linux-spec/for-next (5111711 Merge branch 'for-2.6.37' of git://linux-nfs.org/~bfields/linux)
+$ git merge linux-spec/for-next
+Already up-to-date.
+Merging omap/for-next (322a8b0 Linux 3.1-rc1)
+$ git merge omap/for-next
+Already up-to-date.
+Merging pxa/for-next (19d6c13 [ARM] pxa/hx4700: actually use platform_lcd driver)
+$ git merge pxa/for-next
+Already up-to-date.
+Merging samsung/next-samsung (9edb240 ARM: H1940/RX1950: Change default LED triggers)
+$ git merge samsung/next-samsung
+Already up-to-date.
+Merging s5p/for-next (e914815 Merge branches 'next-samsung-cleanup2' and 'next-samsung-devel2' into for-next)
+$ git merge s5p/for-next
+Merge made by the 'recursive' strategy.
+Merging tegra/for-next (bdd01cc Merge branch 'for-3.3/dt' into for-next)
+$ git merge tegra/for-next
+Merge made by the 'recursive' strategy.
+Merging xilinx/arm-next (b85a3ef ARM: Xilinx: Adding Xilinx board support)
+$ git merge xilinx/arm-next
+Already up-to-date.
+Merging blackfin/for-linus (c2bc3a3 Merge branch 'x86/rdrand' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip)
+$ git merge blackfin/for-linus
+Already up-to-date.
+Merging c6x/for-linux-next (166c0ea C6X: replace tick_nohz_stop/restart_sched_tick calls)
+$ git merge c6x/for-linux-next
+Already up-to-date.
+Merging cris/for-next (ea78f5b CRIS: Update documentation)
+$ git merge cris/for-next
+Auto-merging drivers/net/cris/eth_v10.c
+Auto-merging arch/cris/arch-v32/drivers/cryptocop.c
+Merge made by the 'recursive' strategy.
+ Documentation/cris/README               |   62 +++++++++++++++---------------
+ arch/cris/arch-v32/drivers/cryptocop.c  |    6 +--
+ arch/cris/arch-v32/kernel/ptrace.c      |    2 -
+ arch/cris/include/arch-v32/arch/cache.h |    2 +-
+ drivers/net/cris/eth_v10.c              |    1 -
+ 5 files changed, 34 insertions(+), 39 deletions(-)
+Merging quilt/hexagon (110b372 Remove unneeded include of version.h from arch/hexagon/include/asm/spinlock_types.h)
+$ git merge quilt/hexagon
+Resolved 'arch/hexagon/Kconfig' using previous resolution.
+Auto-merging arch/hexagon/Kconfig
+CONFLICT (content): Merge conflict in arch/hexagon/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master dbe781a] Merge branch 'quilt/hexagon'
+$ git diff -M --stat --summary HEAD^..
+ arch/hexagon/Kconfig                      |   23 ++++-------------------
+ arch/hexagon/Makefile                     |    4 ----
+ arch/hexagon/include/asm/spinlock_types.h |    2 --
+ arch/hexagon/kernel/dma.c                 |    1 +
+ arch/hexagon/kernel/ptrace.c              |    1 +
+ arch/hexagon/kernel/time.c                |    7 +++----
+ arch/hexagon/kernel/vdso.c                |    1 +
+ 7 files changed, 10 insertions(+), 29 deletions(-)
+Merging ia64/next (65cc21b ia64: Add accept4() syscall)
+$ git merge ia64/next
+Already up-to-date.
+Merging m68k/for-next (3bd9e50 m68k/mac: Make CONFIG_HEARTBEAT unavailable on Mac)
+$ git merge m68k/for-next
+Already up-to-date.
+Merging m68knommu/for-next (1f7034b m68k: allow ColdFire 547x and 548x CPUs to be built with MMU enabled)
+$ git merge m68knommu/for-next
+Already up-to-date.
+Merging microblaze/next (ccb19d2 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge microblaze/next
+Already up-to-date.
+Merging mips/mips-for-linux-next (8551715 Merge branches 'fixes-for-linus' and 'next/lantiq' into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Removing arch/mips/lantiq/xway/setup-xway.c
+Removing arch/mips/lantiq/xway/setup-ase.c
+Removing arch/mips/lantiq/xway/pmu.c
+Removing arch/mips/lantiq/xway/ebu.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                                        |    6 +
+ arch/mips/alchemy/common/time.c                    |    2 +-
+ arch/mips/configs/ase_defconfig                    |   79 ++++
+ arch/mips/configs/falcon_defconfig                 |   82 ++++
+ arch/mips/configs/xway_defconfig                   |   80 ++++
+ arch/mips/include/asm/mach-au1x00/gpio-au1300.h    |   20 +-
+ .../include/asm/mach-lantiq/falcon/falcon_irq.h    |  268 +++++++++++++
+ arch/mips/include/asm/mach-lantiq/falcon/irq.h     |   18 +
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h    |  158 ++++++++
+ arch/mips/include/asm/mach-lantiq/lantiq.h         |   23 +-
+ .../mips/include/asm/mach-lantiq/xway/lantiq_irq.h |   22 +-
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |   56 +++-
+ arch/mips/include/asm/page.h                       |    3 -
+ arch/mips/kernel/smp-bmips.c                       |    1 -
+ arch/mips/kernel/vmlinux.lds.S                     |    1 -
+ arch/mips/lantiq/Kconfig                           |    4 +
+ arch/mips/lantiq/Makefile                          |    1 +
+ arch/mips/lantiq/Platform                          |    1 +
+ arch/mips/lantiq/clk.c                             |   25 +--
+ arch/mips/lantiq/devices.c                         |   30 +--
+ arch/mips/lantiq/devices.h                         |    4 +
+ arch/mips/lantiq/early_printk.c                    |   14 +-
+ arch/mips/lantiq/falcon/Kconfig                    |   11 +
+ arch/mips/lantiq/falcon/Makefile                   |    2 +
+ arch/mips/lantiq/falcon/clk.c                      |   44 +++
+ arch/mips/lantiq/falcon/devices.c                  |  128 +++++++
+ arch/mips/lantiq/falcon/devices.h                  |   20 +
+ arch/mips/lantiq/falcon/gpio.c                     |  399 ++++++++++++++++++++
+ arch/mips/lantiq/falcon/mach-easy98000.c           |  110 ++++++
+ arch/mips/lantiq/falcon/prom.c                     |   93 +++++
+ arch/mips/lantiq/falcon/reset.c                    |   88 +++++
+ arch/mips/lantiq/falcon/sysctrl.c                  |  183 +++++++++
+ arch/mips/lantiq/irq.c                             |   24 +-
+ arch/mips/lantiq/machtypes.h                       |    5 +
+ arch/mips/lantiq/prom.c                            |   57 +++-
+ arch/mips/lantiq/prom.h                            |    4 +
+ arch/mips/lantiq/xway/Makefile                     |    6 +-
+ arch/mips/lantiq/xway/devices.c                    |   47 +--
+ arch/mips/lantiq/xway/dma.c                        |   21 +-
+ arch/mips/lantiq/xway/ebu.c                        |   52 ---
+ arch/mips/lantiq/xway/gpio.c                       |   14 +-
+ arch/mips/lantiq/xway/gpio_stp.c                   |   13 +-
+ arch/mips/lantiq/xway/mach-easy50601.c             |    5 +
+ arch/mips/lantiq/xway/pmu.c                        |   69 ----
+ arch/mips/lantiq/xway/prom-ase.c                   |    9 +
+ arch/mips/lantiq/xway/prom-xway.c                  |   10 +
+ arch/mips/lantiq/xway/reset.c                      |   24 +-
+ arch/mips/lantiq/xway/setup-ase.c                  |   19 -
+ arch/mips/lantiq/xway/setup-xway.c                 |   20 -
+ arch/mips/lantiq/xway/sysctrl.c                    |   78 ++++
+ arch/mips/mm/fault.c                               |   36 ++-
+ arch/mips/pci/pci-lantiq.c                         |   40 +-
+ arch/mips/pci/pci.c                                |    5 +-
+ arch/mips/pmc-sierra/yosemite/ht-irq.c             |   10 -
+ arch/mips/txx9/generic/7segled.c                   |    2 +-
+ drivers/net/ethernet/lantiq_etop.c                 |  204 +++++++++--
+ drivers/watchdog/lantiq_wdt.c                      |    2 +-
+ 57 files changed, 2324 insertions(+), 428 deletions(-)
+ create mode 100644 arch/mips/configs/ase_defconfig
+ create mode 100644 arch/mips/configs/falcon_defconfig
+ create mode 100644 arch/mips/configs/xway_defconfig
+ create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
+ create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/irq.h
+ create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+ create mode 100644 arch/mips/lantiq/falcon/Kconfig
+ create mode 100644 arch/mips/lantiq/falcon/Makefile
+ create mode 100644 arch/mips/lantiq/falcon/clk.c
+ create mode 100644 arch/mips/lantiq/falcon/devices.c
+ create mode 100644 arch/mips/lantiq/falcon/devices.h
+ create mode 100644 arch/mips/lantiq/falcon/gpio.c
+ create mode 100644 arch/mips/lantiq/falcon/mach-easy98000.c
+ create mode 100644 arch/mips/lantiq/falcon/prom.c
+ create mode 100644 arch/mips/lantiq/falcon/reset.c
+ create mode 100644 arch/mips/lantiq/falcon/sysctrl.c
+ delete mode 100644 arch/mips/lantiq/xway/ebu.c
+ delete mode 100644 arch/mips/lantiq/xway/pmu.c
+ delete mode 100644 arch/mips/lantiq/xway/setup-ase.c
+ delete mode 100644 arch/mips/lantiq/xway/setup-xway.c
+ create mode 100644 arch/mips/lantiq/xway/sysctrl.c
+Merging openrisc/for-upstream (b6fd41e Linux 3.1-rc6)
+$ git merge openrisc/for-upstream
+Already up-to-date.
+Merging parisc/for-next (fc99a91 futex: Use same lock set as lws calls)
+$ git merge parisc/for-next
+Merge made by the 'recursive' strategy.
+ arch/parisc/include/asm/futex.h |   31 +++++++++++++++++++++++++++----
+ 1 files changed, 27 insertions(+), 4 deletions(-)
+Merging powerpc/next (ef88e39 powerpc: fix compile error with 85xx/p1010rdb.c)
+$ git merge powerpc/next
+Already up-to-date.
+Merging 4xx/next (ef88e39 powerpc: fix compile error with 85xx/p1010rdb.c)
+$ git merge 4xx/next
+Already up-to-date.
+Merging 52xx-and-virtex/powerpc/next (c1395f4 dtc/powerpc: remove obsolete .gitignore entries)
+$ git merge 52xx-and-virtex/powerpc/next
+Merge made by the 'recursive' strategy.
+Merging galak/next (ef88e39 powerpc: fix compile error with 85xx/p1010rdb.c)
+$ git merge galak/next
+Already up-to-date.
+Merging s390/features (f163303 [S390] dasd: revalidate server for new pathgroup)
+$ git merge s390/features
+Merge made by the 'recursive' strategy.
+ arch/s390/Makefile              |    1 -
+ arch/s390/kernel/vmlinux.lds.S  |    4 +-
+ drivers/s390/block/dasd.c       |    6 ++++
+ drivers/s390/block/dasd_alias.c |   64 +--------------------------------------
+ drivers/s390/block/dasd_eckd.c  |   63 ++++++++++++++++++++++----------------
+ drivers/s390/block/dasd_int.h   |    2 +
+ 6 files changed, 48 insertions(+), 92 deletions(-)
+Merging sh/sh-latest (b9a3acf Merge branch 'sh/stable-updates' into sh-latest)
+$ git merge sh/sh-latest
+Already up-to-date.
+Merging rmobile/rmobile-latest (b58c580 Merge branch 'rmobile-fixes-for-linus' into rmobile-latest)
+$ git merge rmobile/rmobile-latest
+Already up-to-date.
+Merging sparc-next/master (e4e1118 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs)
+$ git merge sparc-next/master
+Already up-to-date.
+Merging tile/master (0c90547 arch/tile: use new generic {enable,disable}_percpu_irq() routines)
+$ git merge tile/master
+Already up-to-date.
+Merging unicore32/unicore32 (0994695 Merge branch 'akpm' (aka "Andrew's patch-bomb, take two"))
+$ git merge unicore32/unicore32
+Already up-to-date.
+Merging xtensa/master (29aced6 xtensa: remove defining register numbers)
+$ git merge xtensa/master
+Merge made by the 'recursive' strategy.
+ arch/xtensa/include/asm/irqflags.h |    1 +
+ arch/xtensa/include/asm/regs.h     |   91 ++++++++++++++++++---------------
+ arch/xtensa/include/asm/timex.h    |    4 +-
+ arch/xtensa/include/asm/uaccess.h  |    2 +-
+ arch/xtensa/kernel/align.S         |   14 +++---
+ arch/xtensa/kernel/coprocessor.S   |   10 ++--
+ arch/xtensa/kernel/entry.S         |   98 ++++++++++++++++++------------------
+ arch/xtensa/kernel/head.S          |   12 ++--
+ arch/xtensa/kernel/irq.c           |    5 ++
+ arch/xtensa/kernel/traps.c         |    4 +-
+ arch/xtensa/kernel/vectors.S       |   22 ++++----
+ arch/xtensa/kernel/vmlinux.lds.S   |    1 +
+ 12 files changed, 139 insertions(+), 125 deletions(-)
+Merging ceph/for-next (83eb26a ceph: ensure prealloc_blob is in place when removing xattr)
+$ git merge ceph/for-next
+Already up-to-date.
+Merging cifs/master (acbbb76 CIFS: Rename *UCS* functions to *UTF16*)
+$ git merge cifs/master
+Auto-merging security/keys/user_defined.c
+Merge made by the 'recursive' strategy.
+ fs/cifs/Kconfig              |    3 +-
+ fs/cifs/cifs_debug.c         |   11 ++-
+ fs/cifs/cifs_spnego.c        |   10 +-
+ fs/cifs/cifs_unicode.c       |   41 +++---
+ fs/cifs/cifs_unicode.h       |   20 ++--
+ fs/cifs/cifsacl.c            |    2 +
+ fs/cifs/cifsencrypt.c        |   21 ++-
+ fs/cifs/cifsglob.h           |    2 +
+ fs/cifs/cifssmb.c            |  162 ++++++++++++-----------
+ fs/cifs/connect.c            |  305 ++++++++++++++++++++++++++++++++++--------
+ fs/cifs/readdir.c            |    9 +-
+ fs/cifs/sess.c               |   34 +++---
+ fs/cifs/smbencrypt.c         |    2 +-
+ include/keys/user-type.h     |    3 +-
+ security/keys/internal.h     |    1 +
+ security/keys/key.c          |    1 +
+ security/keys/user_defined.c |   37 +++++
+ 17 files changed, 462 insertions(+), 202 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 configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (1209f49 eCryptfs: infinite loop due to overflow in ecryptfs_write())
+$ git merge ecryptfs/next
+Merge made by the 'recursive' strategy.
+ fs/ecryptfs/crypto.c          |   68 ++++++++++++++++++++++++++++++++++++----
+ fs/ecryptfs/ecryptfs_kernel.h |    5 +++
+ fs/ecryptfs/keystore.c        |    9 ++---
+ fs/ecryptfs/read_write.c      |    4 +-
+ fs/ecryptfs/super.c           |   14 ++++++++-
+ 5 files changed, 84 insertions(+), 16 deletions(-)
+Merging ext3/for_next (46fe44c quota: Pass information that quota is stored in system file to userspace)
+$ git merge ext3/for_next
+Merge made by the 'recursive' strategy.
+ fs/ext2/ioctl.c       |   22 ++++++++++++++++------
+ fs/jbd/checkpoint.c   |   27 ++++++++++++++++++++++-----
+ fs/jbd/recovery.c     |    4 ++++
+ fs/quota/dquot.c      |    8 +++++---
+ include/linux/quota.h |    6 +++++-
+ 5 files changed, 52 insertions(+), 15 deletions(-)
+Merging ext4/dev (d50f2ab ext4: fix undefined behavior in ext4_fill_flex_info())
+$ git merge ext4/dev
+Already up-to-date.
+Merging fatfs/master (710d440 fat: fat16 support maximum 4GB file/vol size as WinXP or 7.)
+$ git merge fatfs/master
+Already up-to-date.
+Merging fuse/for-next (03c9693 cuse: implement memory mapping)
+$ git merge fuse/for-next
+Auto-merging fs/fuse/inode.c
+Auto-merging fs/fuse/fuse_i.h
+Merge made by the 'recursive' strategy.
+ fs/fuse/cuse.c       |  426 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ fs/fuse/dev.c        |  155 ++-----------------
+ fs/fuse/fuse_i.h     |   35 ++++-
+ fs/fuse/inode.c      |  167 +++++++++++++++++++-
+ include/linux/fuse.h |   25 +++
+ 5 files changed, 656 insertions(+), 152 deletions(-)
+Merging gfs2/master (53999bf error: implicit declaration of function 'module_flags_taint')
+$ git merge gfs2/master
+Already up-to-date.
+Merging hfsplus/for-next (6596528 hfsplus: ensure bio requests are not smaller than the hardware sectors)
+$ git merge hfsplus/for-next
+Already up-to-date.
+Merging jfs/next (1c8007b jfs: flush journal completely before releasing metadata inodes)
+$ git merge jfs/next
+Already up-to-date.
+Merging logfs/master (21f3eb8 logfs: update page reference count for pined pages)
+$ git merge logfs/master
+Resolved 'fs/logfs/dev_mtd.c' using previous resolution.
+Resolved 'fs/logfs/file.c' using previous resolution.
+Auto-merging fs/logfs/super.c
+Auto-merging fs/logfs/readwrite.c
+Auto-merging fs/logfs/logfs.h
+Auto-merging fs/logfs/inode.c
+Auto-merging fs/logfs/file.c
+CONFLICT (content): Merge conflict in fs/logfs/file.c
+Auto-merging fs/logfs/dir.c
+Auto-merging fs/logfs/dev_mtd.c
+CONFLICT (content): Merge conflict in fs/logfs/dev_mtd.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 8a8478e] Merge remote-tracking branch 'logfs/master'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS          |    1 +
+ fs/logfs/dev_mtd.c   |   26 +++++++++++-------------
+ fs/logfs/dir.c       |    2 +-
+ fs/logfs/file.c      |    2 +
+ fs/logfs/gc.c        |    2 +-
+ fs/logfs/inode.c     |    4 ++-
+ fs/logfs/journal.c   |    1 -
+ fs/logfs/logfs.h     |    5 +++-
+ fs/logfs/readwrite.c |   51 +++++++++++++++++++++++++++++++++----------------
+ fs/logfs/segment.c   |   51 ++++++++++++++++++++++++++++++++++++++-----------
+ fs/logfs/super.c     |    3 +-
+ 11 files changed, 99 insertions(+), 49 deletions(-)
+Merging nfs/linux-next (90a4c0f uml: fix compile for x86-64)
+$ git merge nfs/linux-next
+Already up-to-date.
+Merging nfsd/nfsd-next (7a6ef8c nfsd4: nfsd4_create_clid_dir return value is unused)
+$ git merge nfsd/nfsd-next
+Already up-to-date.
+Merging nilfs2/for-next (93ee7a9 Linux 3.1-rc2)
+$ git merge nilfs2/for-next
+Already up-to-date.
+Merging ocfs2/linux-next (9392557 ocfs2: avoid unaligned access to dqc_bitmap)
+$ git merge ocfs2/linux-next
+Already up-to-date.
+Merging omfs/for-next (976d167 Linux 3.1-rc9)
+$ git merge omfs/for-next
+Already up-to-date.
+Merging squashfs/master (3d4a1c8 Squashfs: fix i_blocks calculation with extended regular files)
+$ git merge squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (f766619 fs/9p: iattr_valid flags are kernel internal flags map them to 9p values.)
+$ git merge v9fs/for-next
+Already up-to-date.
+Merging ubifs/linux-next (1f4f434 UBI: use own macros for the layout volume)
+$ git merge ubifs/linux-next
+Already up-to-date.
+Merging xfs/master (d060646 xfs: cleanup xfs_file_aio_write)
+$ git merge xfs/master
+Already up-to-date.
+Merging vfs/for-next (a25a2b8 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security)
+$ git merge vfs/for-next
+Already up-to-date.
+Merging vfs-scale/vfs-scale-working (32385c7 kernel: fix hlist_bl again)
+$ git merge vfs-scale/vfs-scale-working
+Already up-to-date.
+Merging pci/linux-next (76ccc29 x86/PCI: Expand the x86_msi_ops to have a restore MSIs.)
+$ git merge pci/linux-next
+Already up-to-date.
+Merging hid/for-next (f62f619 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid)
+$ git merge hid/for-next
+Already up-to-date.
+Merging quilt/i2c (ccb19d2 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge quilt/i2c
+Already up-to-date.
+Merging bjdooks-i2c/next-i2c (fc84fe1 Merge branch 'for_3.3/i2c/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into for-33/i2c/omap)
+$ git merge bjdooks-i2c/next-i2c
+Merge made by the 'recursive' strategy.
+Merging quilt/jdelvare-hwmon (ccb19d2 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge quilt/jdelvare-hwmon
+Already up-to-date.
+Merging hwmon-staging/hwmon-next (80b0ed5 hwmon: (w83627hf) Fix checkpatch issues)
+$ git merge hwmon-staging/hwmon-next
+Merge made by the 'recursive' strategy.
+ drivers/hwmon/abituguru.c        |  162 ++++++++++------
+ drivers/hwmon/abituguru3.c       |   56 ++++--
+ drivers/hwmon/ad7414.c           |    6 +-
+ drivers/hwmon/ad7418.c           |   12 +-
+ drivers/hwmon/adm1021.c          |   30 +++-
+ drivers/hwmon/adm1025.c          |   63 +++++--
+ drivers/hwmon/adm1026.c          |  400 ++++++++++++++++++++++++-------------
+ drivers/hwmon/adm1029.c          |   10 +-
+ drivers/hwmon/adm9240.c          |   66 +++++--
+ drivers/hwmon/adt7411.c          |    2 +-
+ drivers/hwmon/adt7462.c          |  111 +++++------
+ drivers/hwmon/adt7470.c          |    6 +-
+ drivers/hwmon/adt7475.c          |    2 +-
+ drivers/hwmon/amc6821.c          |    2 +-
+ drivers/hwmon/asb100.c           |   67 +++++--
+ drivers/hwmon/asus_atk0110.c     |    3 +-
+ drivers/hwmon/atxp1.c            |   99 ++++++----
+ drivers/hwmon/dme1737.c          |  217 +++++++++-----------
+ drivers/hwmon/ds1621.c           |   32 ++--
+ drivers/hwmon/f71805f.c          |  163 +++++++++++-----
+ drivers/hwmon/f71882fg.c         |    2 +-
+ drivers/hwmon/fschmd.c           |   57 ++++--
+ drivers/hwmon/g760a.c            |    4 +-
+ drivers/hwmon/gl518sm.c          |   88 ++++++---
+ drivers/hwmon/gl520sm.c          |  127 +++++++++---
+ drivers/hwmon/hwmon-vid.c        |   24 ++--
+ drivers/hwmon/hwmon.c            |    5 +-
+ drivers/hwmon/i5k_amb.c          |   18 ++-
+ drivers/hwmon/ibmaem.c           |    2 +-
+ drivers/hwmon/k10temp.c          |    2 +-
+ drivers/hwmon/k8temp.c           |   17 +-
+ drivers/hwmon/lm70.c             |    2 +-
+ drivers/hwmon/lm77.c             |   69 +++++---
+ drivers/hwmon/lm78.c             |  103 +++++++---
+ drivers/hwmon/lm80.c             |  158 ++++++++++++----
+ drivers/hwmon/lm83.c             |   17 ++-
+ drivers/hwmon/lm85.c             |  130 ++++++++++---
+ drivers/hwmon/lm87.c             |  237 +++++++++++++++-------
+ drivers/hwmon/lm92.c             |   52 ++++--
+ drivers/hwmon/lm93.c             |  408 +++++++++++++++++++++++++-------------
+ drivers/hwmon/max1619.c          |   21 ++-
+ drivers/hwmon/max6650.c          |  113 ++++++-----
+ drivers/hwmon/mc13783-adc.c      |    2 +-
+ drivers/hwmon/pc87360.c          |  404 ++++++++++++++++++++++++--------------
+ drivers/hwmon/pcf8591.c          |   63 ++++--
+ drivers/hwmon/pmbus/pmbus_core.c |    2 +-
+ drivers/hwmon/sht15.c            |    2 +-
+ drivers/hwmon/sis5595.c          |  140 +++++++++----
+ drivers/hwmon/smm665.c           |    2 +-
+ drivers/hwmon/smsc47m1.c         |   74 +++++--
+ drivers/hwmon/smsc47m192.c       |   74 +++++--
+ drivers/hwmon/thmc50.c           |   33 +++-
+ drivers/hwmon/ultra45_env.c      |   28 ++-
+ drivers/hwmon/via686a.c          |   78 ++++++--
+ drivers/hwmon/vt1211.c           |  126 ++++++++-----
+ drivers/hwmon/vt8231.c           |  129 +++++++++----
+ drivers/hwmon/w83627hf.c         |  144 ++++++++++----
+ drivers/hwmon/w83781d.c          |  146 +++++++++-----
+ drivers/hwmon/w83791d.c          |  115 ++++++++----
+ drivers/hwmon/w83792d.c          |  263 +++++++++++++++---------
+ drivers/hwmon/w83793.c           |  221 +++++++++++++--------
+ drivers/hwmon/w83l785ts.c        |    2 +-
+ drivers/hwmon/w83l786ng.c        |  105 +++++++----
+ drivers/hwmon/wm831x-hwmon.c     |    2 +-
+ 64 files changed, 3529 insertions(+), 1791 deletions(-)
+Merging quilt/kernel-doc (5851bad The Japanese/Korean/Chinese versions still need updating.)
+$ git merge quilt/kernel-doc
+Auto-merging Documentation/sysctl/kernel.txt
+Merge made by the 'recursive' strategy.
+ Documentation/sysctl/kernel.txt |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+Merging docs/docs-move (5c24d8b Merge branch 'docs/docbook/drm' of git://github.com/mfwitten/linux into docs-move)
+$ git merge docs/docs-move
+Already up-to-date.
+Merging v4l-dvb/master (36be126 [media] as3645a: Fix compilation by including slab.h)
+$ git merge v4l-dvb/master
+Already up-to-date.
+Merging kbuild/for-next (b1e0fba Merge branch 'kbuild/kconfig' into kbuild/for-next)
+$ git merge kbuild/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging kconfig/for-next (eae1c36 Merge branch 'kconfig/for-linus-2' into kconfig/for-next)
+$ git merge kconfig/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging libata/NEXT (b73fa46 [libata] ata_piix: Add Toshiba Satellite Pro A120 to the quirks list due to broken suspend functionality.)
+$ git merge libata/NEXT
+Already up-to-date.
+Merging infiniband/for-next (1583676 Merge branches 'cma', 'misc', 'mlx4', 'nes', 'qib' and 'uverbs' into for-next)
+$ git merge infiniband/for-next
+Already up-to-date.
+Merging acpi/next (b9bf644 Merge branch 'einj-null-fix' into build)
+$ git merge acpi/next
+Merge made by the 'recursive' strategy.
+ drivers/acpi/apei/einj.c |    7 ++++++-
+ 1 files changed, 6 insertions(+), 1 deletions(-)
+Merging cpupowerutils/master (498ca79 cpupower: use man(1) when calling "cpupower help subcommand")
+$ git merge cpupowerutils/master
+Already up-to-date.
+Merging ieee1394/for-next (2ca526b MAINTAINERS: firewire git URL update)
+$ git merge ieee1394/for-next
+Already up-to-date.
+Merging ubi/linux-next (805a6af Linux 3.2)
+$ git merge ubi/linux-next
+Already up-to-date.
+Merging dlm/next (60f98d1 dlm: add recovery callbacks)
+$ git merge dlm/next
+Already up-to-date.
+Merging scsi/master (76ffe8a [SCSI] libfc: remove redundant timer init for fcp)
+$ git merge scsi/master
+Already up-to-date.
+Merging target-updates/for-next (895f302 target: Set additional sense length field in sense data)
+$ git merge target-updates/for-next
+Already up-to-date.
+Merging target-merge/for-next-merge (a42d985 ib_srpt: Initial SRP Target merge for v3.3-rc1)
+$ git merge target-merge/for-next-merge
+Already up-to-date.
+Merging ibft/linux-next (935a9fe ibft: Fix finding IBFT ACPI table on UEFI)
+$ git merge ibft/linux-next
+Already up-to-date.
+Merging slave-dma/next (e08b881 ARM: mach-shmobile: specify CHCLR registers on SH7372)
+$ git merge slave-dma/next
+Already up-to-date.
+Merging async_tx/next (21ef4b8 dmaengine: use DEFINE_IDR for static initialization)
+$ git merge async_tx/next
+Already up-to-date.
+Merging net-next/master (356b954 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k)
+$ git merge net-next/master
+Already up-to-date.
+Merging wireless-next/master (c3b5003 tg3: Fix single-vector MSI-X code)
+$ git merge wireless-next/master
+Already up-to-date.
+Merging bluetooth/master (c5993de Bluetooth: Correct packet len calculation)
+$ git merge bluetooth/master
+Already up-to-date.
+Merging mtd/master (f5eee48 mtd: cfi: AMD/Fujitsu compatibles: add panic write support)
+$ git merge mtd/master
+Auto-merging drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+Merge made by the 'recursive' strategy.
+ drivers/mtd/chips/cfi_cmdset_0002.c   |  240 +++++++++++++++++++++++++++++++++
+ drivers/mtd/nand/gpmi-nand/gpmi-lib.c |   18 ++-
+ drivers/mtd/nand/nand_base.c          |    2 +-
+ fs/jffs2/erase.c                      |    2 +-
+ 4 files changed, 256 insertions(+), 6 deletions(-)
+Merging l2-mtd/master (8be70fd MTD: ST SPEAr: Add SMI driver for serial NOR flash)
+$ git merge l2-mtd/master
+Resolved 'drivers/mtd/nand/gpmi-nand/gpmi-lib.c' using previous resolution.
+Auto-merging drivers/mtd/nand/nand_base.c
+Auto-merging drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+CONFLICT (content): Merge conflict in drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 7f21a5c] Merge remote-tracking branch 'l2-mtd/master'
+$ git diff -M --stat --summary HEAD^..
+ drivers/mtd/devices/Kconfig     |    7 +
+ drivers/mtd/devices/Makefile    |    1 +
+ drivers/mtd/devices/pmc551.c    |    4 +-
+ drivers/mtd/devices/spear_smi.c | 1114 +++++++++++++++++++++++++++++++++++++++
+ drivers/mtd/mtd_blkdevs.c       |    1 +
+ drivers/mtd/mtdblock.c          |    8 +-
+ drivers/mtd/mtdcore.c           |    4 +-
+ drivers/mtd/nand/nand_base.c    |   63 ++-
+ drivers/mtd/onenand/samsung.c   |    4 +-
+ include/linux/mtd/blktrans.h    |    1 +
+ include/linux/mtd/mtd.h         |    4 +-
+ include/linux/mtd/nand.h        |    5 +-
+ include/linux/mtd/spear_smi.h   |   62 +++
+ 13 files changed, 1244 insertions(+), 34 deletions(-)
+ create mode 100644 drivers/mtd/devices/spear_smi.c
+ create mode 100644 include/linux/mtd/spear_smi.h
+Merging crypto/master (b85a088 crypto: sha512 - use standard ror64())
+$ git merge crypto/master
+Auto-merging crypto/sha512_generic.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-tegra/fuse.c                   |    2 +
+ arch/x86/crypto/blowfish_glue.c              |   30 +
+ arch/x86/crypto/serpent-sse2-i586-asm_32.S   |   29 +-
+ arch/x86/crypto/serpent-sse2-x86_64-asm_64.S |   29 +-
+ arch/x86/crypto/twofish_glue_3way.c          |   47 ++
+ crypto/sha512_generic.c                      |   13 +-
+ drivers/char/hw_random/tx4939-rng.c          |    5 +-
+ drivers/crypto/Kconfig                       |   11 +
+ drivers/crypto/Makefile                      |    1 +
+ drivers/crypto/caam/caamalg.c                |  126 +++-
+ drivers/crypto/geode-aes.c                   |    6 +-
+ drivers/crypto/hifn_795x.c                   |    3 +-
+ drivers/crypto/ixp4xx_crypto.c               |    4 +-
+ drivers/crypto/mv_cesa.c                     |   12 +-
+ drivers/crypto/n2_core.c                     |    7 +-
+ drivers/crypto/omap-aes.c                    |    8 +-
+ drivers/crypto/omap-sham.c                   |    4 +
+ drivers/crypto/picoxcell_crypto.c            |   46 +-
+ drivers/crypto/s5p-sss.c                     |    6 +-
+ drivers/crypto/talitos.c                     |    1 +
+ drivers/crypto/tegra-aes.c                   | 1096 ++++++++++++++++++++++++++
+ drivers/crypto/tegra-aes.h                   |  103 +++
+ include/linux/bitops.h                       |   20 +
+ include/linux/crypto.h                       |    5 +
+ 24 files changed, 1539 insertions(+), 75 deletions(-)
+ create mode 100644 drivers/crypto/tegra-aes.c
+ create mode 100644 drivers/crypto/tegra-aes.h
+Merging sound/for-next (387dbd1 Merge branch 'fix/hda' into for-next)
+$ git merge sound/for-next
+Merge made by the 'recursive' strategy.
+ sound/pci/hda/alc880_quirks.c |   17 ++++++++++----
+ sound/pci/hda/alc882_quirks.c |   15 ++++++++----
+ sound/pci/hda/patch_realtek.c |   48 ++++++++++++++++++++++++++--------------
+ 3 files changed, 53 insertions(+), 27 deletions(-)
+Merging sound-asoc/for-next (14af6bd Merge branch 'for-3.3' into asoc-next)
+$ git merge sound-asoc/for-next
+Auto-merging sound/soc/codecs/sgtl5000.c
+Merge made by the 'recursive' strategy.
+ sound/soc/codecs/sgtl5000.c      |   17 +++++--
+ sound/soc/codecs/tlv320aic32x4.c |  110 +++++++++++++++++--------------------
+ 2 files changed, 64 insertions(+), 63 deletions(-)
+Merging cpufreq/next (6c523c6 [CPUFREQ] EXYNOS: Removed useless headers and codes)
+$ git merge cpufreq/next
+Already up-to-date.
+Merging quilt/rr (53999bf error: implicit declaration of function 'module_flags_taint')
+$ git merge quilt/rr
+Already up-to-date.
+Merging input/next (dab78d7 Input: tc3589x-keypad - add missing kerneldoc)
+$ git merge input/next
+Already up-to-date.
+Merging input-mt/next (02f8c6a Linux 3.0)
+$ git merge input-mt/next
+Already up-to-date.
+Merging lsm/for-next (ca05a99 capabilities: remain source compatible with 32-bit raw legacy capability support.)
+$ git merge lsm/for-next
+Already up-to-date.
+Merging block/for-next (b3021da Merge branch 'for-3.3/core' into for-next)
+$ git merge block/for-next
+Merge made by the 'recursive' strategy.
+Merging quilt/device-mapper (90a4c0f uml: fix compile for x86-64)
+$ git merge quilt/device-mapper
+Already up-to-date.
+Merging embedded/master (4744b43 embedded: fix vc_translate operator precedence)
+$ git merge embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a20 firmware: speed up request_firmware(), v3)
+$ git merge firmware/master
+Already up-to-date.
+Merging pcmcia/master (74411c0 smc91c92_cs.c: fix bogus compiler warning)
+$ git merge pcmcia/master
+Already up-to-date.
+Merging battery/master (913272b Merge git://git.infradead.org/users/cbou/battery-urgent)
+$ git merge battery/master
+Already up-to-date.
+Merging mmc/mmc-next (0ac9f78 mmc: MMC-4.5 Data Tag Support)
+$ git merge mmc/mmc-next
+Merge made by the 'recursive' strategy.
+ drivers/mmc/card/block.c |   21 ++++++++++++++++-----
+ drivers/mmc/core/mmc.c   |   14 ++++++++++++++
+ include/linux/mmc/card.h |    2 ++
+ include/linux/mmc/mmc.h  |    3 +++
+ 4 files changed, 35 insertions(+), 5 deletions(-)
+Merging kgdb/kgdb-next (880ba69 lib: rename pack_hex_byte() to hex_byte_pack())
+$ git merge kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+Merging slab/for-next (a1450d6 Merge branch 'slab/urgent' into for-next)
+$ git merge slab/for-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging uclinux/for-next (5e442a4 Revert "proc: fix races against execve() of /proc/PID/fd**")
+$ git merge uclinux/for-next
+Already up-to-date.
+Merging md/for-next (307729c md/raid1: perform bad-block tests for WriteMostly devices too.)
+$ git merge md/for-next
+Already up-to-date.
+Merging mfd/for-next (74d836c rtc: max8925: Add function to work as wakeup source)
+$ git merge mfd/for-next
+Already up-to-date.
+Merging hdlc/hdlc-next (4a6908a Linux 2.6.28)
+$ git merge hdlc/hdlc-next
+Already up-to-date.
+Merging drm/drm-next (095f979 drm/nouveau/pm: fix build with HWMON off)
+$ git merge drm/drm-next
+Already up-to-date.
+Merging fbdev/fbdev-next (f787f32 module_param: make bool parameters really bool (drivers/video/i810))
+$ git merge fbdev/fbdev-next
+Already up-to-date.
+Merging viafb/viafb-next (4ce36bb viafb: replace strict_strtoul to kstrto* and check return value)
+$ git merge viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (9a90168 OMAPDSS: HDMI: Disable DDC internal pull up)
+$ git merge omap_dss2/for-next
+Already up-to-date.
+Merging regulator/for-next (0c437c4 regulator: set constraints.apply_uV to 0 in of_get_fixed_voltage_config)
+$ git merge regulator/for-next
+Already up-to-date.
+Merging security/next (7b7e591 ima: fix invalid memory reference)
+$ git merge security/next
+Already up-to-date.
+Merging selinux/master (f423e5b capabilities: remove __cap_full_set definition)
+$ git merge selinux/master
+Already up-to-date.
+Merging lblnet/master (7e27d6e Linux 2.6.35-rc3)
+$ git merge lblnet/master
+Already up-to-date.
+Merging watchdog/linux-next (a79dcc5 watchdog: imx2_wdt.c: use devm_request_and_ioremap)
+$ git merge watchdog/linux-next
+Merge made by the 'recursive' strategy.
+ drivers/watchdog/dw_wdt.c       |    6 +-----
+ drivers/watchdog/hpwdt.c        |    5 +++--
+ drivers/watchdog/imx2_wdt.c     |   11 +----------
+ drivers/watchdog/nuc900_wdt.c   |    5 +++--
+ drivers/watchdog/omap_wdt.c     |    2 ++
+ drivers/watchdog/via_wdt.c      |    2 +-
+ drivers/watchdog/wafer5823wdt.c |    4 ++--
+ drivers/watchdog/wm8350_wdt.c   |    4 ++--
+ 8 files changed, 15 insertions(+), 24 deletions(-)
+Merging bdev/master (feaf384 Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block)
+$ git merge bdev/master
+Already up-to-date.
+Merging dwmw2-iommu/master (c3b92c8 Linux 3.1)
+$ git merge dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (1a51a0c ARM: OMAP3: fix build on !CONFIG_IOMMU_API)
+$ git merge iommu/next
+Already up-to-date.
+Merging osd/linux-next (724577c ore: Must support none-PAGE-aligned IO)
+$ git merge osd/linux-next
+Already up-to-date.
+Merging jc_docs/docs-next (5c050fb docs: update the development process document)
+$ git merge jc_docs/docs-next
+Already up-to-date.
+Merging nommu/master (0ce790e Linux 2.6.39-rc1)
+$ git merge nommu/master
+Already up-to-date.
+Merging trivial/for-next (9879326 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial)
+$ git merge trivial/for-next
+Already up-to-date.
+Merging audit/for-next (def5754 Audit: remove spaces from audit_log_d_path)
+$ git merge audit/for-next
+Already up-to-date.
+Merging pm/linux-next (7208162 PM / Hibernate: Rewrite unlock_system_sleep() to fix s2disk regression)
+$ git merge pm/linux-next
+Merge made by the 'recursive' strategy.
+ Documentation/power/basic-pm-debugging.txt |    2 +-
+ Documentation/power/freezing-of-tasks.txt  |    8 ++++----
+ include/linux/suspend.h                    |   19 +++++++++++++++++--
+ kernel/power/snapshot.c                    |    3 ++-
+ 4 files changed, 24 insertions(+), 8 deletions(-)
+Merging apm/for-next (b4a133d Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm)
+$ git merge apm/for-next
+Already up-to-date.
+Merging fsnotify/for-next (ef9bf3b fanotify: only destroy a mark if both its mask and its ignored_mask are cleared)
+$ git merge fsnotify/for-next
+Auto-merging include/linux/fsnotify_backend.h
+Auto-merging fs/notify/mark.c
+Auto-merging fs/notify/group.c
+Auto-merging fs/notify/fanotify/fanotify_user.c
+Auto-merging fs/nfsd/vfs.c
+Auto-merging fs/cachefiles/namei.c
+Merge made by the 'recursive' strategy.
+ fs/cachefiles/namei.c              |    1 -
+ fs/cachefiles/xattr.c              |    1 -
+ fs/nfsd/vfs.c                      |    3 -
+ fs/notify/dnotify/dnotify.c        |   15 +++---
+ fs/notify/fanotify/fanotify.c      |   24 +++++----
+ fs/notify/fanotify/fanotify_user.c |  101 +++++++++++++++++++++++++-----------
+ fs/notify/group.c                  |    1 +
+ fs/notify/mark.c                   |   36 +++++--------
+ include/linux/fanotify.h           |    5 ++-
+ include/linux/fsnotify_backend.h   |   14 ++++-
+ 10 files changed, 121 insertions(+), 80 deletions(-)
+Merging irda/for-next (94d57c4 enic: Update MAINTAINERS)
+$ git merge irda/for-next
+Already up-to-date.
+Merging edac/linux_next (4d096ca MAINTAINERS: add an entry for Edac Sandy Bridge driver)
+$ git merge edac/linux_next
+Already up-to-date.
+Merging edac-amd/for-next (ed8ccfa Merge branch '3.3-edac-scrubrate' into edac-for-next)
+$ git merge edac-amd/for-next
+Auto-merging drivers/edac/edac_mc_sysfs.c
+Merge made by the 'recursive' strategy.
+ Documentation/edac.txt       |    4 ++--
+ drivers/edac/amd64_edac.c    |   32 ++++++++++++++++++++++++++++----
+ drivers/edac/edac_mc_sysfs.c |    4 ++--
+ 3 files changed, 32 insertions(+), 8 deletions(-)
+Merging devicetree/devicetree/next (661db79 of/irq: Add interrupts-names property to name an irq resource)
+$ git merge devicetree/devicetree/next
+Already up-to-date.
+Merging spi/spi/next (14c173e spi/tegra: depend instead of select TEGRA_SYSTEM_DMA)
+$ git merge spi/spi/next
+Already up-to-date.
+Merging gpio/gpio/next (f408c98 GPIO: sa1100: implement proper gpiolib gpio_to_irq conversion)
+$ git merge gpio/gpio/next
+Already up-to-date.
+Merging tip/auto-latest (eb5a6fe Merge branch 'x86/urgent' into auto-latest)
+$ git merge tip/auto-latest
+Auto-merging mm/mmap.c
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/mm.h
+Merge made by the 'recursive' strategy.
+ arch/x86/lib/copy_page_64.S |   12 ++++--------
+ include/linux/mm.h          |    1 +
+ include/linux/sched.h       |    2 +-
+ kernel/rcutorture.c         |    8 ++++----
+ kernel/time/tick-sched.c    |    8 ++++++++
+ mm/memblock.c               |    7 +++++--
+ mm/mmap.c                   |    5 +++++
+ 7 files changed, 28 insertions(+), 15 deletions(-)
+Merging rcu/rcu/next (f0312a5 rcu: Bring RTFP.txt up to date.)
+$ git merge rcu/rcu/next
+Merge made by the 'recursive' strategy.
+ Documentation/RCU/RTFP.txt | 1908 ++++++++++++++++++++++++++++++++++++++++----
+ 1 files changed, 1757 insertions(+), 151 deletions(-)
+Merging cputime/cputime (c3e0ef9 [S390] fix cputime overflow in uptime_proc_show)
+$ git merge cputime/cputime
+Already up-to-date.
+Merging uprobes/for-next (af1d40c perf: perf interface for uprobes)
+$ git merge uprobes/for-next
+Auto-merging tools/perf/util/symbol.h
+Auto-merging tools/perf/util/symbol.c
+Auto-merging tools/perf/builtin-probe.c
+Auto-merging mm/mmap.c
+Auto-merging kernel/trace/trace.h
+Auto-merging kernel/signal.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/Makefile
+Auto-merging include/linux/srcu.h
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/mm_types.h
+Auto-merging arch/x86/kernel/signal.c
+Auto-merging arch/x86/kernel/Makefile
+Auto-merging arch/x86/include/asm/thread_info.h
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/Kconfig
+Merge made by the 'recursive' strategy.
+ Documentation/trace/uprobetracer.txt    |   93 ++
+ arch/Kconfig                            |    3 +
+ arch/x86/Kconfig                        |    5 +-
+ arch/x86/include/asm/thread_info.h      |    2 +
+ arch/x86/include/asm/uprobes.h          |   59 ++
+ arch/x86/kernel/Makefile                |    1 +
+ arch/x86/kernel/signal.c                |    6 +
+ arch/x86/kernel/uprobes.c               |  674 ++++++++++++++
+ include/linux/mm_types.h                |    5 +
+ include/linux/sched.h                   |    4 +
+ include/linux/srcu.h                    |   43 +
+ include/linux/uprobes.h                 |  171 ++++
+ kernel/Makefile                         |    1 +
+ kernel/fork.c                           |   15 +
+ kernel/signal.c                         |    3 +
+ kernel/trace/Kconfig                    |   20 +
+ kernel/trace/Makefile                   |    2 +
+ kernel/trace/trace.h                    |    5 +
+ kernel/trace/trace_kprobe.c             |  899 +-----------------
+ kernel/trace/trace_probe.c              |  786 ++++++++++++++++
+ kernel/trace/trace_probe.h              |  162 ++++
+ kernel/trace/trace_uprobe.c             |  768 +++++++++++++++
+ kernel/uprobes.c                        | 1546 +++++++++++++++++++++++++++++++
+ mm/mmap.c                               |   33 +-
+ tools/perf/Documentation/perf-probe.txt |   14 +
+ tools/perf/builtin-probe.c              |   49 +-
+ tools/perf/util/probe-event.c           |  428 +++++++--
+ tools/perf/util/probe-event.h           |   12 +-
+ tools/perf/util/symbol.c                |    8 +
+ tools/perf/util/symbol.h                |    1 +
+ 30 files changed, 4830 insertions(+), 988 deletions(-)
+ create mode 100644 Documentation/trace/uprobetracer.txt
+ create mode 100644 arch/x86/include/asm/uprobes.h
+ create mode 100644 arch/x86/kernel/uprobes.c
+ create mode 100644 include/linux/uprobes.h
+ create mode 100644 kernel/trace/trace_probe.c
+ create mode 100644 kernel/trace/trace_probe.h
+ create mode 100644 kernel/trace/trace_uprobe.c
+ create mode 100644 kernel/uprobes.c
+$ git am -3 ../patches/0001-uprobes-bad-merge-fix.patch
+Applying: uprobes: bad merge fix
+$ git reset HEAD^
+Unstaged changes after reset:
+M	include/linux/srcu.h
+$ git add .
+$ git commit -v -a --amend
+[master 3e94d85] Merge remote-tracking branch 'uprobes/for-next'
+Merging cgroup/for-next (6b3da11 Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu)
+$ git merge cgroup/for-next
+Already up-to-date.
+Merging kmemleak/kmemleak (1502dde kmemleak: only scan non-zero-size section)
+$ git merge kmemleak/kmemleak
+Merge made by the 'recursive' strategy.
+ mm/kmemleak.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+Merging kvm/linux-next (da69dee KVM: PPC: Whitespace fix for kvm.h)
+$ git merge kvm/linux-next
+Already up-to-date.
+Merging oprofile/for-next (42fcb11 Merge branch 'oprofile/perf-ibs-v4' into oprofile/for-next)
+$ git merge oprofile/for-next
+Resolved 'tools/perf/util/header.c' using previous resolution.
+Resolved 'tools/perf/util/header.h' using previous resolution.
+Auto-merging tools/perf/util/parse-events.c
+Auto-merging tools/perf/util/header.h
+CONFLICT (content): Merge conflict in tools/perf/util/header.h
+Auto-merging tools/perf/util/header.c
+CONFLICT (content): Merge conflict in tools/perf/util/header.c
+Auto-merging tools/perf/builtin-record.c
+Auto-merging arch/x86/include/asm/perf_event.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 5719d04] Merge remote-tracking branch 'oprofile/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/x86/include/asm/msr-index.h         |    5 +
+ arch/x86/include/asm/perf_event.h        |    2 +
+ arch/x86/kernel/cpu/perf_event_amd_ibs.c |  438 +++++++++++++++++++++++++++++-
+ tools/perf/builtin-record.c              |   28 +--
+ tools/perf/scripts/perl/bin/ibs-record   |   23 ++
+ tools/perf/scripts/perl/bin/ibs-report   |    6 +
+ tools/perf/scripts/perl/ibs.pl           |   47 ++++
+ tools/perf/util/header.c                 |  443 +++++++++++++++++++-----------
+ tools/perf/util/header.h                 |    2 +
+ tools/perf/util/parse-events.c           |   84 ++++++-
+ 10 files changed, 885 insertions(+), 193 deletions(-)
+ create mode 100644 tools/perf/scripts/perl/bin/ibs-record
+ create mode 100644 tools/perf/scripts/perl/bin/ibs-report
+ create mode 100644 tools/perf/scripts/perl/ibs.pl
+Merging xen/upstream/xen (59e9a6b Merge branch 'upstream/ticketlock-cleanup' into upstream/xen)
+$ git merge xen/upstream/xen
+Resolved 'arch/x86/include/asm/cmpxchg.h' using previous resolution.
+Auto-merging arch/x86/include/asm/cmpxchg.h
+CONFLICT (content): Merge conflict in arch/x86/include/asm/cmpxchg.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master a6657e7] Merge remote-tracking branch 'xen/upstream/xen'
+$ git diff -M --stat --summary HEAD^..
+Merging xen-two/linux-next (429de5a Merge branch 'stable/for-linus-fixes-3.3' into linux-next)
+$ git merge xen-two/linux-next
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging xen-pvhvm/linux-next (b056b6a xen: suspend: remove xen_hvm_suspend)
+$ git merge xen-pvhvm/linux-next
+Already up-to-date.
+Merging percpu/for-next (6b3da11 Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu)
+$ git merge percpu/for-next
+Already up-to-date.
+Merging workqueues/for-next (6b3da11 Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu)
+$ git merge workqueues/for-next
+Already up-to-date.
+Merging sfi/sfi-test (5b026c4 SFI: use ioremap_cache() instead of ioremap())
+$ git merge sfi/sfi-test
+Already up-to-date.
+Merging asm-generic/next (35dbc0e asm-generic/io.h: allow people to override individual funcs)
+$ git merge asm-generic/next
+Already up-to-date.
+Merging drivers-x86/linux-next (15b956a acer-wmi: support Lenovo ideapad S205 wifi switch)
+$ git merge drivers-x86/linux-next
+Already up-to-date.
+Merging hwpoison/hwpoison (46e387b Merge branch 'hwpoison-hugepages' into hwpoison)
+$ git merge hwpoison/hwpoison
+Already up-to-date.
+Merging sysctl/master (c2f5631 sysctl: remove impossible condition check)
+$ git merge sysctl/master
+Auto-merging fs/proc/proc_sysctl.c
+Merge made by the 'recursive' strategy.
+ fs/proc/proc_sysctl.c |   14 ++------------
+ 1 files changed, 2 insertions(+), 12 deletions(-)
+Merging namespace/master (7e05c93 proc: Fix the proc access checks to namespace files.)
+$ git merge namespace/master
+Auto-merging fs/proc/namespaces.c
+Auto-merging fs/proc/inode.c
+Merge made by the 'recursive' strategy.
+ fs/proc/inode.c      |    6 +-
+ fs/proc/namespaces.c |  160 +++++++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 142 insertions(+), 24 deletions(-)
+Merging regmap/for-next (0a92815 mfd: Clearing events requires event registers to be writable for da9052-core)
+$ git merge regmap/for-next
+Already up-to-date.
+Merging hsi/for-next (43139a6 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge hsi/for-next
+Auto-merging include/linux/Kbuild
+Auto-merging drivers/Makefile
+Auto-merging drivers/Kconfig
+Auto-merging Documentation/ioctl/ioctl-number.txt
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/device-drivers.tmpl |   17 +
+ Documentation/ioctl/ioctl-number.txt      |    1 +
+ drivers/Kconfig                           |    2 +
+ drivers/Makefile                          |    1 +
+ drivers/hsi/Kconfig                       |   19 +
+ drivers/hsi/Makefile                      |    6 +
+ drivers/hsi/clients/Kconfig               |   13 +
+ drivers/hsi/clients/Makefile              |    5 +
+ drivers/hsi/clients/hsi_char.c            |  802 +++++++++++++++++++++++++++++
+ drivers/hsi/hsi.c                         |  494 ++++++++++++++++++
+ drivers/hsi/hsi_boardinfo.c               |   62 +++
+ drivers/hsi/hsi_core.h                    |   35 ++
+ include/linux/Kbuild                      |    1 +
+ include/linux/hsi/Kbuild                  |    1 +
+ include/linux/hsi/hsi.h                   |  410 +++++++++++++++
+ include/linux/hsi/hsi_char.h              |   63 +++
+ 16 files changed, 1932 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/hsi/Kconfig
+ create mode 100644 drivers/hsi/Makefile
+ create mode 100644 drivers/hsi/clients/Kconfig
+ create mode 100644 drivers/hsi/clients/Makefile
+ create mode 100644 drivers/hsi/clients/hsi_char.c
+ create mode 100644 drivers/hsi/hsi.c
+ create mode 100644 drivers/hsi/hsi_boardinfo.c
+ create mode 100644 drivers/hsi/hsi_core.h
+ create mode 100644 include/linux/hsi/Kbuild
+ create mode 100644 include/linux/hsi/hsi.h
+ create mode 100644 include/linux/hsi/hsi_char.h
+Merging driver-core/driver-core-next (90a4c0f uml: fix compile for x86-64)
+$ git merge driver-core/driver-core-next
+Already up-to-date.
+Merging tty/tty-next (6b3da11 Merge branch 'for-3.3' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu)
+$ git merge tty/tty-next
+Already up-to-date.
+Merging usb/usb-next (90a4c0f uml: fix compile for x86-64)
+$ git merge usb/usb-next
+Already up-to-date.
+Merging staging/staging-next (90a4c0f uml: fix compile for x86-64)
+$ git merge staging/staging-next
+Already up-to-date.
+Merging char-misc/char-misc-next (90a4c0f uml: fix compile for x86-64)
+$ git merge char-misc/char-misc-next
+Already up-to-date.
+Merging bkl-config/config (4ba8216 BKL: That's all, folks)
+$ git merge bkl-config/config
+Already up-to-date.
+Merging tmem/linux-next (805a6af Linux 3.2)
+$ git merge tmem/linux-next
+Already up-to-date.
+Merging writeback/writeback-for-next (bc31b86 writeback: move MIN_WRITEBACK_PAGES to fs-writeback.c)
+$ git merge writeback/writeback-for-next
+Already up-to-date.
+Merging arm-dt/devicetree/arm-next (ede338f dt: add documentation of ARM dt boot interface)
+$ git merge arm-dt/devicetree/arm-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcf hwspinlock: add MAINTAINERS entries)
+$ git merge hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (0d2006b pinctrl: remove unnecessary max pin number)
+$ git merge pinctrl/for-next
+Already up-to-date.
+Merging moduleh/for-sfr (6aec187 drivers/media: video/a5k6aa is a module and so needs module.h)
+$ git merge moduleh/for-sfr
+Already up-to-date.
+Merging vhost/linux-next (193a667 alpha: drop pci_iomap/pci_iounmap from pci-noop.c)
+$ git merge vhost/linux-next
+Already up-to-date.
+Merging kmap_atomic/kmap_atomic (2c2c817 feature-removal-schedule.txt: add the deprecated form of kmap_atomic())
+$ git merge kmap_atomic/kmap_atomic
+Auto-merging kernel/power/snapshot.c
+Auto-merging fs/logfs/segment.c
+Auto-merging fs/logfs/readwrite.c
+Auto-merging fs/logfs/dir.c
+Auto-merging fs/fuse/dev.c
+Auto-merging fs/ecryptfs/read_write.c
+Auto-merging drivers/target/tcm_fc/tfc_io.c
+Auto-merging drivers/target/target_core_transport.c
+Removing drivers/staging/rtl8192u/ieee80211/kmap_types.h
+Auto-merging drivers/scsi/scsi_lib.c
+Auto-merging drivers/scsi/megaraid.c
+Auto-merging drivers/scsi/libfc/fc_lport.c
+Auto-merging drivers/scsi/libfc/fc_fcp.c
+Auto-merging drivers/scsi/fcoe/fcoe.c
+Auto-merging drivers/scsi/cxgbi/libcxgbi.c
+Auto-merging drivers/crypto/hifn_795x.c
+Auto-merging Documentation/feature-removal-schedule.txt
+Merge made by the 'recursive' strategy.
+ Documentation/feature-removal-schedule.txt       |    9 ++
+ arch/arm/include/asm/highmem.h                   |    2 +-
+ arch/arm/mm/copypage-fa.c                        |   12 ++--
+ arch/arm/mm/copypage-feroceon.c                  |   12 ++--
+ arch/arm/mm/copypage-v3.c                        |   12 ++--
+ arch/arm/mm/copypage-v4mc.c                      |    8 +-
+ arch/arm/mm/copypage-v4wb.c                      |   12 ++--
+ arch/arm/mm/copypage-v4wt.c                      |   12 ++--
+ arch/arm/mm/copypage-v6.c                        |   12 ++--
+ arch/arm/mm/copypage-xsc3.c                      |   12 ++--
+ arch/arm/mm/copypage-xscale.c                    |    8 +-
+ arch/arm/mm/highmem.c                            |    4 +-
+ arch/frv/include/asm/highmem.h                   |    2 +-
+ arch/frv/mm/highmem.c                            |    4 +-
+ arch/mips/include/asm/highmem.h                  |    2 +-
+ arch/mips/mm/c-r4k.c                             |    4 +-
+ arch/mips/mm/highmem.c                           |    4 +-
+ arch/mips/mm/init.c                              |    8 +-
+ arch/mn10300/include/asm/highmem.h               |    2 +-
+ arch/parisc/include/asm/cacheflush.h             |    2 +-
+ arch/powerpc/include/asm/highmem.h               |    2 +-
+ arch/powerpc/kvm/book3s_pr.c                     |    4 +-
+ arch/powerpc/mm/dma-noncoherent.c                |    5 +-
+ arch/powerpc/mm/hugetlbpage.c                    |    4 +-
+ arch/powerpc/mm/mem.c                            |    4 +-
+ arch/sh/mm/cache-sh4.c                           |    4 +-
+ arch/sh/mm/cache.c                               |   12 ++--
+ arch/sparc/include/asm/highmem.h                 |    2 +-
+ arch/sparc/mm/highmem.c                          |    4 +-
+ arch/tile/include/asm/highmem.h                  |    2 +-
+ arch/tile/mm/highmem.c                           |    4 +-
+ arch/um/kernel/skas/uaccess.c                    |    4 +-
+ arch/x86/crypto/aesni-intel_glue.c               |   24 +++---
+ arch/x86/include/asm/highmem.h                   |    2 +-
+ arch/x86/kernel/crash_dump_32.c                  |    6 +-
+ arch/x86/kvm/lapic.c                             |    8 +-
+ arch/x86/kvm/paging_tmpl.h                       |    4 +-
+ arch/x86/kvm/x86.c                               |    8 +-
+ arch/x86/lib/usercopy_32.c                       |    4 +-
+ arch/x86/mm/highmem_32.c                         |    4 +-
+ crypto/ahash.c                                   |    4 +-
+ crypto/async_tx/async_memcpy.c                   |    8 +-
+ crypto/blkcipher.c                               |    8 +-
+ crypto/ccm.c                                     |    4 +-
+ crypto/scatterwalk.c                             |    8 +-
+ crypto/shash.c                                   |    8 +-
+ drivers/ata/libata-sff.c                         |    8 +-
+ drivers/block/brd.c                              |   20 +++---
+ drivers/block/drbd/drbd_bitmap.c                 |   50 ++++++------
+ drivers/block/drbd/drbd_nl.c                     |    4 +-
+ drivers/block/loop.c                             |   16 ++--
+ drivers/block/pktcdvd.c                          |    8 +-
+ drivers/crypto/hifn_795x.c                       |   10 +-
+ drivers/edac/edac_mc.c                           |    4 +-
+ drivers/gpu/drm/drm_cache.c                      |    8 +-
+ drivers/gpu/drm/ttm/ttm_tt.c                     |   16 ++--
+ drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c              |    6 +-
+ drivers/ide/ide-taskfile.c                       |    4 +-
+ drivers/infiniband/ulp/iser/iser_memory.c        |    8 +-
+ drivers/md/bitmap.c                              |   42 +++++-----
+ drivers/md/dm-crypt.c                            |    8 +-
+ drivers/media/video/ivtv/ivtv-udma.c             |    4 +-
+ drivers/memstick/host/jmb38x_ms.c                |    4 +-
+ drivers/memstick/host/tifm_ms.c                  |    4 +-
+ drivers/net/ethernet/intel/e1000/e1000_main.c    |    6 +-
+ drivers/net/ethernet/intel/e1000e/netdev.c       |   10 +--
+ drivers/net/ethernet/sun/cassini.c               |    4 +-
+ drivers/scsi/arcmsr/arcmsr_hba.c                 |    8 +-
+ drivers/scsi/bnx2fc/bnx2fc_fcoe.c                |    5 +-
+ drivers/scsi/cxgbi/libcxgbi.c                    |    5 +-
+ drivers/scsi/fcoe/fcoe.c                         |    4 +-
+ drivers/scsi/fcoe/fcoe_transport.c               |    5 +-
+ drivers/scsi/gdth.c                              |    4 +-
+ drivers/scsi/ips.c                               |    6 +-
+ drivers/scsi/isci/request.c                      |   16 ++--
+ drivers/scsi/libfc/fc_fcp.c                      |    8 +-
+ drivers/scsi/libfc/fc_libfc.c                    |    8 +-
+ drivers/scsi/libfc/fc_libfc.h                    |    2 +-
+ drivers/scsi/libfc/fc_lport.c                    |    2 +-
+ drivers/scsi/libiscsi_tcp.c                      |    4 +-
+ drivers/scsi/libsas/sas_host_smp.c               |    8 +-
+ drivers/scsi/megaraid.c                          |    4 +-
+ drivers/scsi/mvsas/mv_sas.c                      |    4 +-
+ drivers/scsi/scsi_debug.c                        |   24 +++---
+ drivers/scsi/scsi_lib.c                          |    4 +-
+ drivers/scsi/sd_dif.c                            |   12 ++--
+ drivers/staging/gma500/mmu.c                     |   30 ++++----
+ drivers/staging/hv/storvsc_drv.c                 |   31 +++----
+ drivers/staging/pohmelfs/inode.c                 |    8 +-
+ drivers/staging/rtl8192u/ieee80211/cipher.c      |    8 +-
+ drivers/staging/rtl8192u/ieee80211/digest.c      |    8 +-
+ drivers/staging/rtl8192u/ieee80211/internal.h    |   17 ----
+ drivers/staging/rtl8192u/ieee80211/kmap_types.h  |   20 -----
+ drivers/staging/rtl8192u/ieee80211/scatterwalk.c |   19 +---
+ drivers/staging/zcache/zcache-main.c             |   16 ++--
+ drivers/staging/zram/xvmalloc.c                  |   39 +++++-----
+ drivers/staging/zram/zram_drv.c                  |   44 +++++-----
+ drivers/target/target_core_transport.c           |    4 +-
+ drivers/target/tcm_fc/tfc_io.c                   |   10 +--
+ drivers/vhost/vhost.c                            |    4 +-
+ fs/afs/fsclient.c                                |    8 +-
+ fs/afs/mntpt.c                                   |    4 +-
+ fs/aio.c                                         |   30 ++++----
+ fs/bio-integrity.c                               |   10 +-
+ fs/btrfs/compression.c                           |   12 ++--
+ fs/btrfs/extent_io.c                             |   16 ++--
+ fs/btrfs/file-item.c                             |    4 +-
+ fs/btrfs/inode.c                                 |   26 +++---
+ fs/btrfs/lzo.c                                   |    4 +-
+ fs/btrfs/scrub.c                                 |    8 +-
+ fs/btrfs/zlib.c                                  |    4 +-
+ fs/ecryptfs/mmap.c                               |    4 +-
+ fs/ecryptfs/read_write.c                         |    8 +-
+ fs/exec.c                                        |    4 +-
+ fs/exofs/dir.c                                   |    4 +-
+ fs/ext2/dir.c                                    |    4 +-
+ fs/fuse/dev.c                                    |    4 +-
+ fs/fuse/file.c                                   |    4 +-
+ fs/gfs2/aops.c                                   |   12 ++--
+ fs/gfs2/lops.c                                   |    8 +-
+ fs/gfs2/quota.c                                  |    4 +-
+ fs/jbd/journal.c                                 |   12 ++--
+ fs/jbd/transaction.c                             |    4 +-
+ fs/jbd2/commit.c                                 |    4 +-
+ fs/jbd2/journal.c                                |   12 ++--
+ fs/jbd2/transaction.c                            |    4 +-
+ fs/logfs/dir.c                                   |   18 ++--
+ fs/logfs/readwrite.c                             |   38 +++++-----
+ fs/logfs/segment.c                               |    4 +-
+ fs/minix/dir.c                                   |    4 +-
+ fs/namei.c                                       |    4 +-
+ fs/nfs/dir.c                                     |    8 +-
+ fs/nfs/nfs4proc.c                                |    4 +-
+ fs/nilfs2/cpfile.c                               |   94 +++++++++++-----------
+ fs/nilfs2/dat.c                                  |   38 +++++-----
+ fs/nilfs2/dir.c                                  |    4 +-
+ fs/nilfs2/ifile.c                                |    4 +-
+ fs/nilfs2/mdt.c                                  |    4 +-
+ fs/nilfs2/page.c                                 |    8 +-
+ fs/nilfs2/recovery.c                             |    4 +-
+ fs/nilfs2/segbuf.c                               |    4 +-
+ fs/nilfs2/sufile.c                               |   68 ++++++++--------
+ fs/ntfs/aops.c                                   |   20 +++---
+ fs/ntfs/attrib.c                                 |   20 +++---
+ fs/ntfs/file.c                                   |   16 ++--
+ fs/ntfs/super.c                                  |    8 +-
+ fs/ocfs2/aops.c                                  |   16 ++--
+ fs/pipe.c                                        |    8 +-
+ fs/reiserfs/stree.c                              |    4 +-
+ fs/reiserfs/tail_conversion.c                    |    4 +-
+ fs/splice.c                                      |    7 +-
+ fs/squashfs/file.c                               |    8 +-
+ fs/squashfs/symlink.c                            |    4 +-
+ fs/ubifs/file.c                                  |    4 +-
+ fs/udf/file.c                                    |    4 +-
+ include/crypto/scatterwalk.h                     |   28 +------
+ include/linux/bio.h                              |    8 +-
+ include/linux/highmem.h                          |   79 +++++++++++++-----
+ kernel/debug/kdb/kdb_support.c                   |    4 +-
+ kernel/power/snapshot.c                          |   28 +++---
+ lib/scatterlist.c                                |    4 +-
+ lib/swiotlb.c                                    |    5 +-
+ mm/bounce.c                                      |    4 +-
+ mm/filemap.c                                     |    8 +-
+ mm/ksm.c                                         |   12 ++--
+ mm/memory.c                                      |    4 +-
+ mm/shmem.c                                       |    4 +-
+ mm/swapfile.c                                    |   30 ++++----
+ mm/vmalloc.c                                     |    8 +-
+ net/core/kmap_skb.h                              |    4 +-
+ net/rds/ib_recv.c                                |    7 +-
+ net/rds/info.c                                   |    6 +-
+ net/rds/iw_recv.c                                |    7 +-
+ net/rds/loop.c                                   |    2 +-
+ net/rds/rds.h                                    |    2 +-
+ net/rds/recv.c                                   |    2 +-
+ net/rds/tcp_recv.c                               |   11 +--
+ net/sunrpc/auth_gss/gss_krb5_wrap.c              |    4 +-
+ net/sunrpc/socklib.c                             |    4 +-
+ net/sunrpc/xdr.c                                 |   20 +++---
+ net/sunrpc/xprtrdma/rpc_rdma.c                   |    8 +-
+ security/tomoyo/domain.c                         |    4 +-
+ 182 files changed, 918 insertions(+), 967 deletions(-)
+ delete mode 100644 drivers/staging/rtl8192u/ieee80211/kmap_types.h
+Merging xshm/xshm-for-next (0d0ab68 caif-xshm: Add CAIF driver for Shared memory for M7400)
+$ git merge xshm/xshm-for-next
+Auto-merging include/linux/Kbuild
+Auto-merging drivers/Makefile
+Auto-merging drivers/Kconfig
+Merge made by the 'recursive' strategy.
+ drivers/Kconfig                   |    2 +
+ drivers/Makefile                  |    1 +
+ drivers/net/caif/Kconfig          |   10 +
+ drivers/net/caif/Makefile         |    1 +
+ drivers/net/caif/caif_xshm.c      |  915 +++++++++++++++++++++++++++
+ drivers/xshm/Kconfig              |   61 ++
+ drivers/xshm/Makefile             |    5 +
+ drivers/xshm/dummy_c2c_genio.c    |   76 +++
+ drivers/xshm/xshm_boot.c          | 1150 +++++++++++++++++++++++++++++++++
+ drivers/xshm/xshm_bus.c           |  113 ++++
+ drivers/xshm/xshm_chr.c           | 1262 +++++++++++++++++++++++++++++++++++++
+ drivers/xshm/xshm_dev.c           |  546 ++++++++++++++++
+ drivers/xshm/xshm_ipctoc.h        |  153 +++++
+ include/linux/Kbuild              |    1 +
+ include/linux/c2c_genio.h         |  195 ++++++
+ include/linux/xshm/Kbuild         |    1 +
+ include/linux/xshm/xshm_dev.h     |  245 +++++++
+ include/linux/xshm/xshm_netlink.h |   95 +++
+ 18 files changed, 4832 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/net/caif/caif_xshm.c
+ create mode 100644 drivers/xshm/Kconfig
+ create mode 100644 drivers/xshm/Makefile
+ create mode 100644 drivers/xshm/dummy_c2c_genio.c
+ create mode 100644 drivers/xshm/xshm_boot.c
+ create mode 100644 drivers/xshm/xshm_bus.c
+ create mode 100644 drivers/xshm/xshm_chr.c
+ create mode 100644 drivers/xshm/xshm_dev.c
+ create mode 100644 drivers/xshm/xshm_ipctoc.h
+ create mode 100644 include/linux/c2c_genio.h
+ create mode 100644 include/linux/xshm/Kbuild
+ create mode 100644 include/linux/xshm/xshm_dev.h
+ create mode 100644 include/linux/xshm/xshm_netlink.h
+Merging memblock/memblock-kill-early_node_map (7bd0b0f memblock: Reimplement memblock allocation using reverse free area iterator)
+$ git merge memblock/memblock-kill-early_node_map
+Already up-to-date.
+Merging remoteproc/for-next (238c1e1 rpmsg: depends on EXPERIMENTAL)
+$ git merge remoteproc/for-next
+Auto-merging include/linux/mod_devicetable.h
+Auto-merging drivers/Makefile
+Auto-merging drivers/Kconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-bus-rpmsg    |   75 ++
+ Documentation/remoteproc.txt                 |  324 ++++++
+ Documentation/rpmsg.txt                      |  293 ++++++
+ MAINTAINERS                                  |    7 +
+ arch/arm/plat-omap/include/plat/remoteproc.h |   57 +
+ drivers/Kconfig                              |    4 +
+ drivers/Makefile                             |    2 +
+ drivers/remoteproc/Kconfig                   |   29 +
+ drivers/remoteproc/Makefile                  |    9 +
+ drivers/remoteproc/omap_remoteproc.c         |  238 +++++
+ drivers/remoteproc/omap_remoteproc.h         |   69 ++
+ drivers/remoteproc/remoteproc_core.c         | 1438 ++++++++++++++++++++++++++
+ drivers/remoteproc/remoteproc_debugfs.c      |  179 ++++
+ drivers/remoteproc/remoteproc_internal.h     |   44 +
+ drivers/remoteproc/remoteproc_rpmsg.c        |  295 ++++++
+ drivers/rpmsg/Kconfig                        |   10 +
+ drivers/rpmsg/Makefile                       |    1 +
+ drivers/rpmsg/virtio_rpmsg_bus.c             | 1026 ++++++++++++++++++
+ include/linux/mod_devicetable.h              |    9 +
+ include/linux/remoteproc.h                   |  264 +++++
+ include/linux/rpmsg.h                        |  326 ++++++
+ include/linux/virtio_ids.h                   |    1 +
+ samples/Kconfig                              |    8 +
+ samples/Makefile                             |    2 +-
+ samples/rpmsg/Makefile                       |    1 +
+ samples/rpmsg/rpmsg_client_sample.c          |  100 ++
+ 26 files changed, 4810 insertions(+), 1 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-rpmsg
+ create mode 100644 Documentation/remoteproc.txt
+ create mode 100644 Documentation/rpmsg.txt
+ create mode 100644 arch/arm/plat-omap/include/plat/remoteproc.h
+ create mode 100644 drivers/remoteproc/Kconfig
+ create mode 100644 drivers/remoteproc/Makefile
+ create mode 100644 drivers/remoteproc/omap_remoteproc.c
+ create mode 100644 drivers/remoteproc/omap_remoteproc.h
+ create mode 100644 drivers/remoteproc/remoteproc_core.c
+ create mode 100644 drivers/remoteproc/remoteproc_debugfs.c
+ create mode 100644 drivers/remoteproc/remoteproc_internal.h
+ create mode 100644 drivers/remoteproc/remoteproc_rpmsg.c
+ create mode 100644 drivers/rpmsg/Kconfig
+ create mode 100644 drivers/rpmsg/Makefile
+ create mode 100644 drivers/rpmsg/virtio_rpmsg_bus.c
+ create mode 100644 include/linux/remoteproc.h
+ create mode 100644 include/linux/rpmsg.h
+ create mode 100644 samples/rpmsg/Makefile
+ create mode 100644 samples/rpmsg/rpmsg_client_sample.c
+$ git am -3 ../patches/rpmsg__rename_virtqueue_add_buf_gfp_to_virtqueue_add_buf.patch
+Applying: rpmsg: rename virtqueue_add_buf_gfp to virtqueue_add_buf
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/rpmsg/virtio_rpmsg_bus.c
+$ git add .
+$ git commit -v -a --amend
+[master dd7e627] Merge remote-tracking branch 'remoteproc/for-next'
+$ git am -3 ../patches/fix-for-vring_new_virtqueue-change.patch
+Applying: remoteproc: don't use virtio's weak barriers
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/remoteproc/remoteproc_rpmsg.c
+$ git add .
+$ git commit -v -a --amend
+[master 1503356] Merge remote-tracking branch 'remoteproc/for-next'
+Merging kvmtool/master (0234379 kvm tools: Remove tags/TAGS on "make clean")
+$ git merge kvmtool/master
+Resolved 'include/net/9p/9p.h' using previous resolution.
+Resolved 'scripts/kconfig/Makefile' using previous resolution.
+Auto-merging scripts/kconfig/Makefile
+CONFLICT (content): Merge conflict in scripts/kconfig/Makefile
+Auto-merging include/net/9p/9p.h
+CONFLICT (content): Merge conflict in include/net/9p/9p.h
+Auto-merging arch/x86/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master a19a570] Merge remote-tracking branch 'kvmtool/master'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS                                  |    8 +
+ arch/x86/Kconfig                             |   31 +
+ scripts/kconfig/Makefile                     |    7 +-
+ tools/kvm/.gitignore                         |   11 +
+ tools/kvm/CREDITS-Git                        |   30 +
+ tools/kvm/Documentation/kernel-debugging.txt |   15 +
+ tools/kvm/Documentation/kvm-balloon.txt      |   24 +
+ tools/kvm/Documentation/kvm-debug.txt        |   16 +
+ tools/kvm/Documentation/kvm-list.txt         |   16 +
+ tools/kvm/Documentation/kvm-pause.txt        |   16 +
+ tools/kvm/Documentation/kvm-resume.txt       |   16 +
+ tools/kvm/Documentation/kvm-run.txt          |   62 +
+ tools/kvm/Documentation/kvm-sandbox.txt      |   16 +
+ tools/kvm/Documentation/kvm-setup.txt        |   15 +
+ tools/kvm/Documentation/kvm-stat.txt         |   19 +
+ tools/kvm/Documentation/kvm-stop.txt         |   16 +
+ tools/kvm/Documentation/kvm-version.txt      |   21 +
+ tools/kvm/Documentation/virtio-console.txt   |   41 +
+ tools/kvm/Makefile                           |  364 ++++++
+ tools/kvm/README                             |  109 ++
+ tools/kvm/builtin-balloon.c                  |   80 ++
+ tools/kvm/builtin-debug.c                    |  103 ++
+ tools/kvm/builtin-help.c                     |   63 ++
+ tools/kvm/builtin-list.c                     |  149 +++
+ tools/kvm/builtin-pause.c                    |   88 ++
+ tools/kvm/builtin-resume.c                   |   88 ++
+ tools/kvm/builtin-run.c                      | 1218 ++++++++++++++++++++
+ tools/kvm/builtin-sandbox.c                  |    9 +
+ tools/kvm/builtin-setup.c                    |  232 ++++
+ tools/kvm/builtin-stat.c                     |  127 +++
+ tools/kvm/builtin-stop.c                     |   70 ++
+ tools/kvm/builtin-version.c                  |   15 +
+ tools/kvm/code16gcc.h                        |   15 +
+ tools/kvm/command-list.txt                   |   15 +
+ tools/kvm/config/feature-tests.mak           |  168 +++
+ tools/kvm/config/utilities.mak               |  188 ++++
+ tools/kvm/disk/blk.c                         |   39 +
+ tools/kvm/disk/core.c                        |  242 ++++
+ tools/kvm/disk/qcow.c                        | 1529 ++++++++++++++++++++++++++
+ tools/kvm/disk/raw.c                         |  140 +++
+ tools/kvm/framebuffer.c                      |   68 ++
+ tools/kvm/guest/init.c                       |   38 +
+ tools/kvm/guest/init_stage2.c                |   55 +
+ tools/kvm/guest/passwd                       |    1 +
+ tools/kvm/guest_compat.c                     |   99 ++
+ tools/kvm/hw/i8042.c                         |  348 ++++++
+ tools/kvm/hw/pci-shmem.c                     |  262 +++++
+ tools/kvm/hw/rtc.c                           |  118 ++
+ tools/kvm/hw/serial.c                        |  414 +++++++
+ tools/kvm/hw/vesa.c                          |   78 ++
+ tools/kvm/include/asm/hweight.h              |    8 +
+ tools/kvm/include/bios/memcpy.h              |    9 +
+ tools/kvm/include/kvm/8250-serial.h          |   10 +
+ tools/kvm/include/kvm/apic.h                 |   17 +
+ tools/kvm/include/kvm/brlock.h               |   41 +
+ tools/kvm/include/kvm/builtin-balloon.h      |    9 +
+ tools/kvm/include/kvm/builtin-debug.h        |   18 +
+ tools/kvm/include/kvm/builtin-help.h         |    6 +
+ tools/kvm/include/kvm/builtin-list.h         |   10 +
+ tools/kvm/include/kvm/builtin-pause.h        |    9 +
+ tools/kvm/include/kvm/builtin-resume.h       |    9 +
+ tools/kvm/include/kvm/builtin-run.h          |   11 +
+ tools/kvm/include/kvm/builtin-sandbox.h      |    6 +
+ tools/kvm/include/kvm/builtin-setup.h        |   11 +
+ tools/kvm/include/kvm/builtin-stat.h         |    9 +
+ tools/kvm/include/kvm/builtin-stop.h         |    9 +
+ tools/kvm/include/kvm/builtin-version.h      |    6 +
+ tools/kvm/include/kvm/compiler.h             |   10 +
+ tools/kvm/include/kvm/disk-image.h           |   81 ++
+ tools/kvm/include/kvm/e820.h                 |   12 +
+ tools/kvm/include/kvm/framebuffer.h          |   34 +
+ tools/kvm/include/kvm/guest_compat.h         |    9 +
+ tools/kvm/include/kvm/i8042.h                |   12 +
+ tools/kvm/include/kvm/ioeventfd.h            |   27 +
+ tools/kvm/include/kvm/ioport.h               |   66 ++
+ tools/kvm/include/kvm/irq.h                  |   31 +
+ tools/kvm/include/kvm/kvm-cmd.h              |   17 +
+ tools/kvm/include/kvm/kvm-cpu.h              |   24 +
+ tools/kvm/include/kvm/kvm-ipc.h              |   24 +
+ tools/kvm/include/kvm/kvm.h                  |   91 ++
+ tools/kvm/include/kvm/mutex.h                |   33 +
+ tools/kvm/include/kvm/parse-options.h        |  214 ++++
+ tools/kvm/include/kvm/pci-shmem.h            |   28 +
+ tools/kvm/include/kvm/pci.h                  |   94 ++
+ tools/kvm/include/kvm/qcow.h                 |  133 +++
+ tools/kvm/include/kvm/rbtree-interval.h      |   27 +
+ tools/kvm/include/kvm/read-write.h           |   43 +
+ tools/kvm/include/kvm/rtc.h                  |    6 +
+ tools/kvm/include/kvm/rwsem.h                |   39 +
+ tools/kvm/include/kvm/sdl.h                  |   17 +
+ tools/kvm/include/kvm/segment.h              |   21 +
+ tools/kvm/include/kvm/strbuf.h               |   19 +
+ tools/kvm/include/kvm/symbol.h               |   22 +
+ tools/kvm/include/kvm/term.h                 |   20 +
+ tools/kvm/include/kvm/threadpool.h           |   37 +
+ tools/kvm/include/kvm/types.h                |    7 +
+ tools/kvm/include/kvm/uip.h                  |  358 ++++++
+ tools/kvm/include/kvm/util.h                 |   95 ++
+ tools/kvm/include/kvm/vesa.h                 |   18 +
+ tools/kvm/include/kvm/virtio-9p.h            |   74 ++
+ tools/kvm/include/kvm/virtio-balloon.h       |    8 +
+ tools/kvm/include/kvm/virtio-blk.h           |   13 +
+ tools/kvm/include/kvm/virtio-console.h       |    9 +
+ tools/kvm/include/kvm/virtio-net.h           |   23 +
+ tools/kvm/include/kvm/virtio-pci-dev.h       |   37 +
+ tools/kvm/include/kvm/virtio-pci.h           |   48 +
+ tools/kvm/include/kvm/virtio-rng.h           |    9 +
+ tools/kvm/include/kvm/virtio-trans.h         |   43 +
+ tools/kvm/include/kvm/virtio.h               |   67 ++
+ tools/kvm/include/kvm/vnc.h                  |   14 +
+ tools/kvm/include/linux/bitops.h             |   33 +
+ tools/kvm/include/linux/byteorder.h          |    7 +
+ tools/kvm/include/linux/compiler.h           |   19 +
+ tools/kvm/include/linux/kernel.h             |   39 +
+ tools/kvm/include/linux/module.h             |    6 +
+ tools/kvm/include/linux/prefetch.h           |    6 +
+ tools/kvm/include/linux/types.h              |   51 +
+ tools/kvm/ioeventfd.c                        |  142 +++
+ tools/kvm/ioport.c                           |  134 +++
+ tools/kvm/kvm-cmd.c                          |   91 ++
+ tools/kvm/kvm-cpu.c                          |  175 +++
+ tools/kvm/kvm-ipc.c                          |  205 ++++
+ tools/kvm/kvm.c                              |  533 +++++++++
+ tools/kvm/main.c                             |   19 +
+ tools/kvm/mmio.c                             |  135 +++
+ tools/kvm/net/uip/arp.c                      |   30 +
+ tools/kvm/net/uip/buf.c                      |  114 ++
+ tools/kvm/net/uip/core.c                     |  190 ++++
+ tools/kvm/net/uip/csum.c                     |   92 ++
+ tools/kvm/net/uip/dhcp.c                     |  203 ++++
+ tools/kvm/net/uip/icmp.c                     |   29 +
+ tools/kvm/net/uip/ipv4.c                     |   29 +
+ tools/kvm/net/uip/tcp.c                      |  317 ++++++
+ tools/kvm/net/uip/udp.c                      |  236 ++++
+ tools/kvm/pci.c                              |  185 ++++
+ tools/kvm/powerpc/include/kvm/barrier.h      |    6 +
+ tools/kvm/powerpc/include/kvm/kvm-arch.h     |   71 ++
+ tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h |   66 ++
+ tools/kvm/powerpc/ioport.c                   |   18 +
+ tools/kvm/powerpc/irq.c                      |   40 +
+ tools/kvm/powerpc/kvm-cpu.c                  |  233 ++++
+ tools/kvm/powerpc/kvm.c                      |  193 ++++
+ tools/kvm/symbol.c                           |   98 ++
+ tools/kvm/term.c                             |  166 +++
+ tools/kvm/tests/Makefile                     |   19 +
+ tools/kvm/tests/boot/Makefile                |   13 +
+ tools/kvm/tests/boot/init.c                  |   11 +
+ tools/kvm/tests/kernel/.gitignore            |    2 +
+ tools/kvm/tests/kernel/Makefile              |   20 +
+ tools/kvm/tests/kernel/README                |   16 +
+ tools/kvm/tests/kernel/kernel.S              |    8 +
+ tools/kvm/tests/pit/.gitignore               |    2 +
+ tools/kvm/tests/pit/Makefile                 |   20 +
+ tools/kvm/tests/pit/README                   |   16 +
+ tools/kvm/tests/pit/tick.S                   |  109 ++
+ tools/kvm/ui/sdl.c                           |  280 +++++
+ tools/kvm/ui/vnc.c                           |  218 ++++
+ tools/kvm/util/KVMTOOLS-VERSION-GEN          |   40 +
+ tools/kvm/util/generate-cmdlist.sh           |   23 +
+ tools/kvm/util/kvm-ifup-vbr0                 |    6 +
+ tools/kvm/util/parse-options.c               |  577 ++++++++++
+ tools/kvm/util/rbtree-interval.c             |   90 ++
+ tools/kvm/util/read-write.c                  |  344 ++++++
+ tools/kvm/util/set_private_br.sh             |   51 +
+ tools/kvm/util/strbuf.c                      |   39 +
+ tools/kvm/util/threadpool.c                  |  145 +++
+ tools/kvm/util/util.c                        |  115 ++
+ tools/kvm/virtio/9p-pdu.c                    |  287 +++++
+ tools/kvm/virtio/9p.c                        | 1326 ++++++++++++++++++++++
+ tools/kvm/virtio/balloon.c                   |  275 +++++
+ tools/kvm/virtio/blk.c                       |  273 +++++
+ tools/kvm/virtio/console.c                   |  203 ++++
+ tools/kvm/virtio/core.c                      |  158 +++
+ tools/kvm/virtio/net.c                       |  547 +++++++++
+ tools/kvm/virtio/pci.c                       |  346 ++++++
+ tools/kvm/virtio/rng.c                       |  188 ++++
+ tools/kvm/virtio/trans.c                     |   22 +
+ tools/kvm/x86/bios.c                         |  174 +++
+ tools/kvm/x86/bios/.gitignore                |    3 +
+ tools/kvm/x86/bios/bios-rom.S                |   12 +
+ tools/kvm/x86/bios/e820.c                    |   72 ++
+ tools/kvm/x86/bios/entry.S                   |   92 ++
+ tools/kvm/x86/bios/gen-offsets.sh            |   14 +
+ tools/kvm/x86/bios/int10.c                   |  110 ++
+ tools/kvm/x86/bios/int15.c                   |   18 +
+ tools/kvm/x86/bios/local.S                   |    7 +
+ tools/kvm/x86/bios/macro.S                   |   25 +
+ tools/kvm/x86/bios/memcpy.c                  |   23 +
+ tools/kvm/x86/bios/rom.ld.S                  |   17 +
+ tools/kvm/x86/cpuid.c                        |   55 +
+ tools/kvm/x86/include/kvm/assembly.h         |   24 +
+ tools/kvm/x86/include/kvm/barrier.h          |   16 +
+ tools/kvm/x86/include/kvm/bios-export.h      |   13 +
+ tools/kvm/x86/include/kvm/bios.h             |   88 ++
+ tools/kvm/x86/include/kvm/boot-protocol.h    |   16 +
+ tools/kvm/x86/include/kvm/cpufeature.h       |   41 +
+ tools/kvm/x86/include/kvm/interrupt.h        |   26 +
+ tools/kvm/x86/include/kvm/kvm-arch.h         |   65 ++
+ tools/kvm/x86/include/kvm/kvm-cpu-arch.h     |   49 +
+ tools/kvm/x86/include/kvm/mptable.h          |    8 +
+ tools/kvm/x86/interrupt.c                    |   28 +
+ tools/kvm/x86/ioport.c                       |   59 +
+ tools/kvm/x86/irq.c                          |  193 ++++
+ tools/kvm/x86/kvm-cpu.c                      |  421 +++++++
+ tools/kvm/x86/kvm.c                          |  374 +++++++
+ tools/kvm/x86/mptable.c                      |  280 +++++
+ 206 files changed, 21146 insertions(+), 1 deletions(-)
+ create mode 100644 tools/kvm/.gitignore
+ create mode 100644 tools/kvm/CREDITS-Git
+ create mode 100644 tools/kvm/Documentation/kernel-debugging.txt
+ create mode 100644 tools/kvm/Documentation/kvm-balloon.txt
+ create mode 100644 tools/kvm/Documentation/kvm-debug.txt
+ create mode 100644 tools/kvm/Documentation/kvm-list.txt
+ create mode 100644 tools/kvm/Documentation/kvm-pause.txt
+ create mode 100644 tools/kvm/Documentation/kvm-resume.txt
+ create mode 100644 tools/kvm/Documentation/kvm-run.txt
+ create mode 100644 tools/kvm/Documentation/kvm-sandbox.txt
+ create mode 100644 tools/kvm/Documentation/kvm-setup.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stat.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stop.txt
+ create mode 100644 tools/kvm/Documentation/kvm-version.txt
+ create mode 100644 tools/kvm/Documentation/virtio-console.txt
+ create mode 100644 tools/kvm/Makefile
+ create mode 100644 tools/kvm/README
+ create mode 100644 tools/kvm/builtin-balloon.c
+ create mode 100644 tools/kvm/builtin-debug.c
+ create mode 100644 tools/kvm/builtin-help.c
+ create mode 100644 tools/kvm/builtin-list.c
+ create mode 100644 tools/kvm/builtin-pause.c
+ create mode 100644 tools/kvm/builtin-resume.c
+ create mode 100644 tools/kvm/builtin-run.c
+ create mode 100644 tools/kvm/builtin-sandbox.c
+ create mode 100644 tools/kvm/builtin-setup.c
+ create mode 100644 tools/kvm/builtin-stat.c
+ create mode 100644 tools/kvm/builtin-stop.c
+ create mode 100644 tools/kvm/builtin-version.c
+ create mode 100644 tools/kvm/code16gcc.h
+ create mode 100644 tools/kvm/command-list.txt
+ create mode 100644 tools/kvm/config/feature-tests.mak
+ create mode 100644 tools/kvm/config/utilities.mak
+ create mode 100644 tools/kvm/disk/blk.c
+ create mode 100644 tools/kvm/disk/core.c
+ create mode 100644 tools/kvm/disk/qcow.c
+ create mode 100644 tools/kvm/disk/raw.c
+ create mode 100644 tools/kvm/framebuffer.c
+ create mode 100644 tools/kvm/guest/init.c
+ create mode 100644 tools/kvm/guest/init_stage2.c
+ create mode 100644 tools/kvm/guest/passwd
+ create mode 100644 tools/kvm/guest_compat.c
+ create mode 100644 tools/kvm/hw/i8042.c
+ create mode 100644 tools/kvm/hw/pci-shmem.c
+ create mode 100644 tools/kvm/hw/rtc.c
+ create mode 100644 tools/kvm/hw/serial.c
+ create mode 100644 tools/kvm/hw/vesa.c
+ create mode 100644 tools/kvm/include/asm/hweight.h
+ create mode 100644 tools/kvm/include/bios/memcpy.h
+ create mode 100644 tools/kvm/include/kvm/8250-serial.h
+ create mode 100644 tools/kvm/include/kvm/apic.h
+ create mode 100644 tools/kvm/include/kvm/brlock.h
+ create mode 100644 tools/kvm/include/kvm/builtin-balloon.h
+ create mode 100644 tools/kvm/include/kvm/builtin-debug.h
+ create mode 100644 tools/kvm/include/kvm/builtin-help.h
+ create mode 100644 tools/kvm/include/kvm/builtin-list.h
+ create mode 100644 tools/kvm/include/kvm/builtin-pause.h
+ create mode 100644 tools/kvm/include/kvm/builtin-resume.h
+ create mode 100644 tools/kvm/include/kvm/builtin-run.h
+ create mode 100644 tools/kvm/include/kvm/builtin-sandbox.h
+ create mode 100644 tools/kvm/include/kvm/builtin-setup.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stat.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stop.h
+ create mode 100644 tools/kvm/include/kvm/builtin-version.h
+ create mode 100644 tools/kvm/include/kvm/compiler.h
+ create mode 100644 tools/kvm/include/kvm/disk-image.h
+ create mode 100644 tools/kvm/include/kvm/e820.h
+ create mode 100644 tools/kvm/include/kvm/framebuffer.h
+ create mode 100644 tools/kvm/include/kvm/guest_compat.h
+ create mode 100644 tools/kvm/include/kvm/i8042.h
+ create mode 100644 tools/kvm/include/kvm/ioeventfd.h
+ create mode 100644 tools/kvm/include/kvm/ioport.h
+ create mode 100644 tools/kvm/include/kvm/irq.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cmd.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cpu.h
+ create mode 100644 tools/kvm/include/kvm/kvm-ipc.h
+ create mode 100644 tools/kvm/include/kvm/kvm.h
+ create mode 100644 tools/kvm/include/kvm/mutex.h
+ create mode 100644 tools/kvm/include/kvm/parse-options.h
+ create mode 100644 tools/kvm/include/kvm/pci-shmem.h
+ create mode 100644 tools/kvm/include/kvm/pci.h
+ create mode 100644 tools/kvm/include/kvm/qcow.h
+ create mode 100644 tools/kvm/include/kvm/rbtree-interval.h
+ create mode 100644 tools/kvm/include/kvm/read-write.h
+ create mode 100644 tools/kvm/include/kvm/rtc.h
+ create mode 100644 tools/kvm/include/kvm/rwsem.h
+ create mode 100644 tools/kvm/include/kvm/sdl.h
+ create mode 100644 tools/kvm/include/kvm/segment.h
+ create mode 100644 tools/kvm/include/kvm/strbuf.h
+ create mode 100644 tools/kvm/include/kvm/symbol.h
+ create mode 100644 tools/kvm/include/kvm/term.h
+ create mode 100644 tools/kvm/include/kvm/threadpool.h
+ create mode 100644 tools/kvm/include/kvm/types.h
+ create mode 100644 tools/kvm/include/kvm/uip.h
+ create mode 100644 tools/kvm/include/kvm/util.h
+ create mode 100644 tools/kvm/include/kvm/vesa.h
+ create mode 100644 tools/kvm/include/kvm/virtio-9p.h
+ create mode 100644 tools/kvm/include/kvm/virtio-balloon.h
+ create mode 100644 tools/kvm/include/kvm/virtio-blk.h
+ create mode 100644 tools/kvm/include/kvm/virtio-console.h
+ create mode 100644 tools/kvm/include/kvm/virtio-net.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci-dev.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci.h
+ create mode 100644 tools/kvm/include/kvm/virtio-rng.h
+ create mode 100644 tools/kvm/include/kvm/virtio-trans.h
+ create mode 100644 tools/kvm/include/kvm/virtio.h
+ create mode 100644 tools/kvm/include/kvm/vnc.h
+ create mode 100644 tools/kvm/include/linux/bitops.h
+ create mode 100644 tools/kvm/include/linux/byteorder.h
+ create mode 100644 tools/kvm/include/linux/compiler.h
+ create mode 100644 tools/kvm/include/linux/kernel.h
+ create mode 100644 tools/kvm/include/linux/module.h
+ create mode 100644 tools/kvm/include/linux/prefetch.h
+ create mode 100644 tools/kvm/include/linux/types.h
+ create mode 100644 tools/kvm/ioeventfd.c
+ create mode 100644 tools/kvm/ioport.c
+ create mode 100644 tools/kvm/kvm-cmd.c
+ create mode 100644 tools/kvm/kvm-cpu.c
+ create mode 100644 tools/kvm/kvm-ipc.c
+ create mode 100644 tools/kvm/kvm.c
+ create mode 100644 tools/kvm/main.c
+ create mode 100644 tools/kvm/mmio.c
+ create mode 100644 tools/kvm/net/uip/arp.c
+ create mode 100644 tools/kvm/net/uip/buf.c
+ create mode 100644 tools/kvm/net/uip/core.c
+ create mode 100644 tools/kvm/net/uip/csum.c
+ create mode 100644 tools/kvm/net/uip/dhcp.c
+ create mode 100644 tools/kvm/net/uip/icmp.c
+ create mode 100644 tools/kvm/net/uip/ipv4.c
+ create mode 100644 tools/kvm/net/uip/tcp.c
+ create mode 100644 tools/kvm/net/uip/udp.c
+ create mode 100644 tools/kvm/pci.c
+ create mode 100644 tools/kvm/powerpc/include/kvm/barrier.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/powerpc/ioport.c
+ create mode 100644 tools/kvm/powerpc/irq.c
+ create mode 100644 tools/kvm/powerpc/kvm-cpu.c
+ create mode 100644 tools/kvm/powerpc/kvm.c
+ create mode 100644 tools/kvm/symbol.c
+ create mode 100644 tools/kvm/term.c
+ create mode 100644 tools/kvm/tests/Makefile
+ create mode 100644 tools/kvm/tests/boot/Makefile
+ create mode 100644 tools/kvm/tests/boot/init.c
+ create mode 100644 tools/kvm/tests/kernel/.gitignore
+ create mode 100644 tools/kvm/tests/kernel/Makefile
+ create mode 100644 tools/kvm/tests/kernel/README
+ create mode 100644 tools/kvm/tests/kernel/kernel.S
+ create mode 100644 tools/kvm/tests/pit/.gitignore
+ create mode 100644 tools/kvm/tests/pit/Makefile
+ create mode 100644 tools/kvm/tests/pit/README
+ create mode 100644 tools/kvm/tests/pit/tick.S
+ create mode 100644 tools/kvm/ui/sdl.c
+ create mode 100644 tools/kvm/ui/vnc.c
+ create mode 100755 tools/kvm/util/KVMTOOLS-VERSION-GEN
+ create mode 100755 tools/kvm/util/generate-cmdlist.sh
+ create mode 100755 tools/kvm/util/kvm-ifup-vbr0
+ create mode 100644 tools/kvm/util/parse-options.c
+ create mode 100644 tools/kvm/util/rbtree-interval.c
+ create mode 100644 tools/kvm/util/read-write.c
+ create mode 100755 tools/kvm/util/set_private_br.sh
+ create mode 100644 tools/kvm/util/strbuf.c
+ create mode 100644 tools/kvm/util/threadpool.c
+ create mode 100644 tools/kvm/util/util.c
+ create mode 100644 tools/kvm/virtio/9p-pdu.c
+ create mode 100644 tools/kvm/virtio/9p.c
+ create mode 100644 tools/kvm/virtio/balloon.c
+ create mode 100644 tools/kvm/virtio/blk.c
+ create mode 100644 tools/kvm/virtio/console.c
+ create mode 100644 tools/kvm/virtio/core.c
+ create mode 100644 tools/kvm/virtio/net.c
+ create mode 100644 tools/kvm/virtio/pci.c
+ create mode 100644 tools/kvm/virtio/rng.c
+ create mode 100644 tools/kvm/virtio/trans.c
+ create mode 100644 tools/kvm/x86/bios.c
+ create mode 100644 tools/kvm/x86/bios/.gitignore
+ create mode 100644 tools/kvm/x86/bios/bios-rom.S
+ create mode 100644 tools/kvm/x86/bios/e820.c
+ create mode 100644 tools/kvm/x86/bios/entry.S
+ create mode 100644 tools/kvm/x86/bios/gen-offsets.sh
+ create mode 100644 tools/kvm/x86/bios/int10.c
+ create mode 100644 tools/kvm/x86/bios/int15.c
+ create mode 100644 tools/kvm/x86/bios/local.S
+ create mode 100644 tools/kvm/x86/bios/macro.S
+ create mode 100644 tools/kvm/x86/bios/memcpy.c
+ create mode 100644 tools/kvm/x86/bios/rom.ld.S
+ create mode 100644 tools/kvm/x86/cpuid.c
+ create mode 100644 tools/kvm/x86/include/kvm/assembly.h
+ create mode 100644 tools/kvm/x86/include/kvm/barrier.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios-export.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios.h
+ create mode 100644 tools/kvm/x86/include/kvm/boot-protocol.h
+ create mode 100644 tools/kvm/x86/include/kvm/cpufeature.h
+ create mode 100644 tools/kvm/x86/include/kvm/interrupt.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/mptable.h
+ create mode 100644 tools/kvm/x86/interrupt.c
+ create mode 100644 tools/kvm/x86/ioport.c
+ create mode 100644 tools/kvm/x86/irq.c
+ create mode 100644 tools/kvm/x86/kvm-cpu.c
+ create mode 100644 tools/kvm/x86/kvm.c
+ create mode 100644 tools/kvm/x86/mptable.c
+Merging scsi-post-merge/merge-base:master ()
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git fetch --no-tags ../next refs/heads/quilt/akpm:akpm
+From ../next
+ * [new branch]      quilt/akpm -> akpm
+$ git fetch --no-tags ../next refs/heads/quilt/akpm-base:akpm-base
+From ../next
+ * [new branch]      quilt/akpm-base -> akpm-base
+$ git checkout akpm
+Switched to branch 'akpm'
+$ git rebase --onto master akpm-base
+First, rewinding head to replay your work on top of it...
+Applying: mm: fix NULL ptr dereference in __count_immobile_pages
+Applying: mm: __count_immobile_pages(): make sure the node is online
+Applying: leds: add led driver for Bachmann's ot200
+Applying: ipc/mqueue: simplify reading msgqueue limit
+Applying: kprobes: initialize before using a hlist
+Applying: drivers/video/backlight/adp88x0_bl.c: fix bit testing logic
+Applying: drivers/video/backlight/l4f00242t03.c: return proper error in l4f00242t03_probe if regulator_get() fails
+Applying: proc: clear_refs: do not clear reserved pages
+Applying: mm: memcg: update the correct soft limit tree during migration
+Applying: mm/hugetlb.c: undo change to page mapcount in fault handler
+Applying: kdump: define KEXEC_NOTE_BYTES arch specific for s390x
+Applying: SHM_UNLOCK: fix long unpreemptible section
+Applying: SHM_UNLOCK: fix Unevictable pages stranded after swap
+Applying: mm: fix rss count leakage during migration
+Applying: score: fix off-by-one index into syscall table
+Applying: arch/x86/kernel/nmi_selftest.c needs percpu.h
+Applying: net/netfilter/nf_conntrack_netlink.c: fix Oops on container destroy
+Applying: vfs: fix panic in __d_lookup() with high dentry hashtable counts
+Applying: acerhdf: add support for Aspire 1410 BIOS v1.3314
+Applying: acerhdf: add support for new hardware
+Applying: acerhdf: lowered default temp fanon/fanoff values
+Applying: arch/x86/platform/iris/iris.c: register a platform device and a platform driver
+Applying: x86, olpc-xo15-sci: enable lid close wakeup control through sysfs
+Applying: geos: platform driver for Geos and Geos2 single-board computers
+Applying: x86, olpc: add debugfs interface for EC commands
+Applying: x86, mm: fix the size calculation of mapping tables
+Applying: drivers/platform/x86/sony-laptop.c: fix scancodes
+Applying: arch/arm/mach-ux500/mbox-db5500.c: world-writable sysfs fifo file
+Applying: arm, exec: remove redundant set_fs(USER_DS)
+Applying: net: use this_cpu_xxx replace percpu_xxx funcs
+Applying: xen: use this_cpu_xxx replace percpu_xxx funcs
+Applying: x86: use this_cpu_xxx to replace percpu_xxx funcs
+Applying: x86: change percpu_read_stable() to this_cpu_read_stable()
+Applying: percpu: remove percpu_xxx() functions
+Applying: Subject irqs: fix long-term regression in genirq irq_set_irq_type() handling
+Applying: irqs: fix handling of pending IRQs at request time
+Applying: hrtimers: Special-case zero length sleeps
+Applying: debugobjects: Fix selftest for static warnings
+Applying: drivers/scsi/aacraid/commctrl.c: fix mem leak in aac_send_raw_srb()
+Applying: drivers/scsi/mpt2sas/mpt2sas_base.c: fix mismatch in mpt2sas_base_hard_reset_handler() mutex lock-unlock
+Applying: drivers/scsi/mpt2sas/mpt2sas_scsih.c: spell "primitive" correctly
+Applying: MAINTAINERS: Staging: cx25821: Add L: linux-media
+Applying: drivers/usb/misc/emi26.c & emi62.c: fix warnings
+Applying: mm, oom: avoid looping when chosen thread detaches its mm
+Applying: mm, oom: fold oom_kill_task() into oom_kill_process()
+Applying: mm, oom: do not emit oom killer warning if chosen thread is already exiting
+Applying: mm: add rss counters consistency check
+Applying: mm: postpone migrated page mapping reset
+Applying: mm/vmscan.c: cleanup with s/reclaim_mode/isolate_mode/
+Applying: mm: fix page-faults detection in swap-token logic
+Applying: mm: add extra free kbytes tunable
+Applying: mm-add-extra-free-kbytes-tunable-update
+Applying: mm-add-extra-free-kbytes-tunable-update-checkpatch-fixes
+Applying: memcg: replace MEM_CONT by MEM_RES_CTLR
+Applying: memcg: replace mem and mem_cont stragglers
+Applying: memcg: lru_size instead of MEM_CGROUP_ZSTAT
+Applying: memcg: enum lru_list lru
+Applying: memcg: remove redundant returns
+Applying: hpet: factor timer allocate from open
+Applying: ceph, cifs, nfs, fuse: boolean and / or confusion
+Applying: prctl: add PR_{SET,GET}_CHILD_SUBREAPER to allow simple process supervision
+Applying: prctl-add-pr_setget_child_subreaper-to-allow-simple-process-supervision-fix
+Applying: prctl-add-pr_setget_child_subreaper-to-allow-simple-process-supervision-fix-fix
+Applying: prctl-add-pr_setget_child_subreaper-to-allow-simple-process-supervision-fix-fix-fix
+Applying: vfs: increment iversion when a file is truncated
+Applying: brlocks/lglocks: cleanups
+Applying: brlocks-lglocks-cleanups-checkpatch-fixes
+Applying: backlight: convert backlight i2c drivers to module_i2c_driver
+Applying: backlight: convert backlight spi drivers to module_spi_driver
+Applying: bitops: rename for_each_set_bit_cont() in favor of analogous list.h function
+Applying: bitops: remove for_each_set_bit_cont()
+Applying: bitops: introduce for_each_clear_bit()
+Applying: mtd: use for_each_clear_bit()
+Applying: s390/char: use for_each_clear_bit()
+Applying: uwb: use for_each_clear_bit()
+Applying: x86: use for_each_clear_bit_from()
+Applying: crc32: remove two instances of trailing whitespaces
+Applying: crc32: move long comment about crc32 fundamentals to Documentation/
+Applying: crc32-move-long-comment-about-crc32-fundamentals-to-documentation-fix
+Applying: crc32: simplify unit test code
+Applying: crc32: miscellaneous cleanups
+Applying: crc32: fix mixing of endian-specific types
+Applying: crc32: make CRC_*_BITS definition correspond to actual bit counts
+Applying: crc32: add slice-by-8 algorithm to existing code
+Applying: crc32: optimize loop counter for x86
+Applying: crc32: add note about this patchset to crc32.c
+Applying: crc32: bolt on crc32c
+Applying: crypto: crc32c should use library implementation
+Applying: crc32: add self-test code for crc32c
+Applying: crc32: select an algorithm via Kconfig
+Applying: init/do_mounts.c: create /root if it does not exist
+Applying: rtc-spear: fix for balancing the enable_irq_wake in Power Mgmt
+Applying: rtc/spear: fix for RTC_AIE_ON and RTC_AIE_OFF ioctl errors
+Applying: rtc/rtc-spear: call platform_set_drvdata() before registering rtc device
+Applying: ipc/sem.c: alternatives to preempt_disable()
+Applying: ipc: provide generic compat versions of IPC syscalls
+Applying: sysctl: make kernel.ns_last_pid control dependent on CHECKPOINT_RESTORE
+Applying: ramoops: use pstore interface
+Applying: notify_change(): check that i_mutex is held
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm
+From ../rebase-tmp
+ + 6da3b82...be922c4 akpm       -> akpm  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm (be922c4 notify_change(): check that i_mutex is held)
+$ git merge --no-ff akpm
+Merge made by the 'recursive' strategy.
+ Documentation/00-INDEX                 |    2 +
+ Documentation/ABI/testing/debugfs-olpc |   16 +
+ Documentation/crc32.txt                |  183 +++++
+ Documentation/laptops/sony-laptop.txt  |    5 +
+ Documentation/ramoops.txt              |    8 +-
+ Documentation/sysctl/vm.txt            |   16 +
+ MAINTAINERS                            |    5 +
+ arch/Kconfig                           |    3 +
+ arch/arm/include/asm/processor.h       |    1 -
+ arch/arm/mach-ux500/mbox-db5500.c      |    2 +-
+ arch/mips/Kconfig                      |    1 +
+ arch/powerpc/Kconfig                   |    1 +
+ arch/s390/Kconfig                      |    1 +
+ arch/s390/include/asm/kexec.h          |   18 +
+ arch/score/kernel/entry.S              |    2 +-
+ arch/sparc/Kconfig                     |    1 +
+ arch/tile/include/asm/compat.h         |   11 -
+ arch/tile/kernel/compat.c              |   43 --
+ arch/x86/Kconfig                       |    8 +
+ arch/x86/include/asm/current.h         |    2 +-
+ arch/x86/include/asm/hardirq.h         |    9 +-
+ arch/x86/include/asm/irq_regs.h        |    4 +-
+ arch/x86/include/asm/mmu_context.h     |   12 +-
+ arch/x86/include/asm/percpu.h          |   24 +-
+ arch/x86/include/asm/smp.h             |    4 +-
+ arch/x86/include/asm/stackprotector.h  |    4 +-
+ arch/x86/include/asm/thread_info.h     |    2 +-
+ arch/x86/include/asm/tlbflush.h        |    4 +-
+ arch/x86/kernel/cpu/common.c           |    2 +-
+ arch/x86/kernel/cpu/mcheck/mce.c       |    4 +-
+ arch/x86/kernel/cpu/perf_event.c       |    4 +-
+ arch/x86/kernel/irqinit.c              |    6 +-
+ arch/x86/kernel/nmi_selftest.c         |    1 +
+ arch/x86/kernel/paravirt.c             |   12 +-
+ arch/x86/kernel/process_32.c           |    2 +-
+ arch/x86/kernel/process_64.c           |   12 +-
+ arch/x86/mm/init.c                     |   21 +-
+ arch/x86/mm/tlb.c                      |   10 +-
+ arch/x86/platform/geode/Makefile       |    1 +
+ arch/x86/platform/geode/geos.c         |  128 ++++
+ arch/x86/platform/iris/iris.c          |   67 ++-
+ arch/x86/platform/olpc/olpc-xo15-sci.c |   67 ++
+ arch/x86/platform/olpc/olpc.c          |   86 +++
+ arch/x86/xen/enlighten.c               |    6 +-
+ arch/x86/xen/irq.c                     |    8 +-
+ arch/x86/xen/mmu.c                     |   20 +-
+ arch/x86/xen/multicalls.h              |    2 +-
+ arch/x86/xen/smp.c                     |    2 +-
+ crypto/Kconfig                         |    1 +
+ crypto/crc32c.c                        |   94 +---
+ drivers/char/Kconfig                   |    1 +
+ drivers/char/hpet.c                    |   56 ++-
+ drivers/char/ramoops.c                 |  203 ++++--
+ drivers/leds/Kconfig                   |    7 +
+ drivers/leds/Makefile                  |    1 +
+ drivers/leds/leds-ot200.c              |  171 +++++
+ drivers/mtd/chips/cfi_cmdset_0001.c    |    6 +-
+ drivers/platform/x86/acerhdf.c         |   67 ++-
+ drivers/platform/x86/sony-laptop.c     |   16 +-
+ drivers/rtc/rtc-spear.c                |  100 ++--
+ drivers/s390/char/sclp_cmd.c           |    5 +-
+ drivers/scsi/aacraid/commctrl.c        |    1 +
+ drivers/scsi/mpt2sas/mpt2sas_base.c    |    3 +-
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c   |    6 +-
+ drivers/usb/misc/emi26.c               |    3 -
+ drivers/usb/misc/emi62.c               |    3 -
+ drivers/uwb/allocator.c                |    6 +-
+ drivers/video/backlight/adp8860_bl.c   |   14 +-
+ drivers/video/backlight/adp8870_bl.c   |   14 +-
+ drivers/video/backlight/ams369fg06.c   |   13 +-
+ drivers/video/backlight/corgi_lcd.c    |   12 +-
+ drivers/video/backlight/l4f00242t03.c  |   15 +-
+ drivers/video/backlight/ld9040.c       |   13 +-
+ drivers/video/backlight/lms283gf05.c   |   13 +-
+ drivers/video/backlight/ltv350qv.c     |   12 +-
+ drivers/video/backlight/s6e63m0.c      |   13 +-
+ drivers/video/backlight/tdo24m.c       |   12 +-
+ drivers/video/backlight/tosa_bl.c      |   13 +-
+ drivers/video/backlight/tosa_lcd.c     |   13 +-
+ drivers/video/backlight/vgg2432a4.c    |   15 +-
+ fs/attr.c                              |    8 +-
+ fs/cifs/cifsfs.c                       |    2 +-
+ fs/dcache.c                            |   12 +-
+ fs/file_table.c                        |   17 +-
+ fs/inode.c                             |    8 +-
+ fs/internal.h                          |    3 +-
+ fs/namei.c                             |   24 +-
+ fs/namespace.c                         |  140 ++--
+ fs/pnode.c                             |    4 +-
+ fs/proc/task_mmu.c                     |    3 +
+ fs/proc_namespace.c                    |    4 +-
+ include/linux/bitops.h                 |   13 +-
+ include/linux/compat.h                 |   12 +-
+ include/linux/crc32.h                  |    2 +
+ include/linux/hpet.h                   |    1 +
+ include/linux/kexec.h                  |    2 +
+ include/linux/lglock.h                 |  187 +----
+ include/linux/memcontrol.h             |    2 +-
+ include/linux/mm_types.h               |    1 +
+ include/linux/mmzone.h                 |    2 +-
+ include/linux/percpu.h                 |   54 --
+ include/linux/prctl.h                  |    3 +
+ include/linux/sched.h                  |   12 +
+ include/linux/shmem_fs.h               |    1 +
+ include/linux/swap.h                   |   38 +-
+ include/linux/topology.h               |    4 +-
+ init/do_mounts.c                       |    3 +
+ ipc/compat.c                           |   70 ++-
+ ipc/mqueue.c                           |    3 +-
+ ipc/sem.c                              |  250 +++++--
+ ipc/shm.c                              |   37 +-
+ kernel/Makefile                        |    2 +-
+ kernel/exit.c                          |   33 +-
+ kernel/fork.c                          |   25 +-
+ kernel/hrtimer.c                       |    8 +
+ kernel/irq/chip.c                      |    3 +-
+ kernel/irq/manage.c                    |    5 +-
+ kernel/kprobes.c                       |    2 +-
+ kernel/lglock.c                        |  136 ++++
+ kernel/pid.c                           |    4 +-
+ kernel/pid_namespace.c                 |    6 +-
+ kernel/sys.c                           |    8 +
+ kernel/sysctl.c                        |   11 +-
+ lib/Kconfig                            |   61 ++-
+ lib/crc32.c                            | 1272 ++++++++++++++++++++++++--------
+ lib/crc32defs.h                        |   56 ++-
+ lib/debugobjects.c                     |   14 +-
+ lib/gen_crc32table.c                   |   81 ++-
+ mm/hugetlb.c                           |    9 +-
+ mm/memcontrol.c                        |  123 ++--
+ mm/memory.c                            |   50 +-
+ mm/migrate.c                           |    2 +-
+ mm/oom_kill.c                          |  141 ++---
+ mm/page_alloc.c                        |   58 ++-
+ mm/rmap.c                              |    3 +-
+ mm/shmem.c                             |   53 +-
+ mm/vmscan.c                            |  142 ++---
+ net/ipv4/tcp.c                         |    5 +-
+ net/netfilter/nf_conntrack_netlink.c   |    5 +
+ net/netfilter/xt_TEE.c                 |   12 +-
+ net/socket.c                           |    4 +-
+ tools/perf/util/include/linux/bitops.h |    2 +-
+ 142 files changed, 3387 insertions(+), 1646 deletions(-)
+ create mode 100644 Documentation/ABI/testing/debugfs-olpc
+ create mode 100644 Documentation/crc32.txt
+ create mode 100644 arch/x86/platform/geode/geos.c
+ create mode 100644 drivers/leds/leds-ot200.c
+ create mode 100644 kernel/lglock.c
+$ git am -3 ../patches/0001-percpu-x86-fix-smp_processor_id-s-need-for-this_cpu_.patch
+Applying: percpu: x86: fix smp_processor_id's need for this_cpu_read
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 0000000..6891044
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,13 @@
+Importing hexagon based on v3.2-rc2
+Unchanged quilt series hexagon
+Importing i2c based on ccb19d263fd1c9e34948e2158c53eacbff369344
+Unchanged quilt series i2c
+Importing jdelvare-hwmon based on ccb19d263fd1c9e34948e2158c53eacbff369344
+Unchanged quilt series jdelvare-hwmon
+Importing kernel-doc based on 3.2-rc7
+Unchanged quilt series kernel-doc
+Importing rr based on v3.2-8694-g53999bf
+Unchanged quilt series rr
+Importing device-mapper based on v3.2-9429-g90a4c0f
+	quilt series is empty
+$ git update-ref refs/heads/quilt/device-mapper 90a4c0f51e8e44111a926be6f4c87af3938a79c3
diff --git a/arch/Kconfig b/arch/Kconfig
index 4f55c73..29f9dc3 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -65,6 +65,9 @@ config OPTPROBES
 	depends on KPROBES && HAVE_OPTPROBES
 	depends on !PREEMPT
 
+config UPROBES
+	def_bool n
+
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
 	bool
 	help
@@ -199,4 +202,7 @@ config HAVE_CMPXCHG_LOCAL
 config HAVE_CMPXCHG_DOUBLE
 	bool
 
+config ARCH_WANT_OLD_COMPAT_IPC
+	bool
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 24626b0..bb68e65 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -754,7 +754,7 @@ config ARCH_SA1100
 	select ARCH_HAS_CPUFREQ
 	select CPU_FREQ
 	select GENERIC_CLOCKEVENTS
-	select CLKDEV_LOOKUP
+	select HAVE_CLK
 	select HAVE_SCHED_CLOCK
 	select TICK_ONESHOT
 	select ARCH_REQUIRE_GPIOLIB
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 40319d9..1683bfb 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -160,7 +160,6 @@ machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
 machine-$(CONFIG_ARCH_IMX_V4_V5)	:= imx
 machine-$(CONFIG_ARCH_IMX_V6_V7)	:= imx
-machine-$(CONFIG_ARCH_MX5)		:= mx5
 machine-$(CONFIG_ARCH_MXS)		:= mxs
 machine-$(CONFIG_ARCH_NETX)		:= netx
 machine-$(CONFIG_ARCH_NOMADIK)		:= nomadik
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..71c4c02
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,115 @@
+This file lists all branches that are pulled into the for-next branch
+of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+and their external dependencies.
+
+It also includes a couple of directly applied patches for build breaks with subject
+The next/* branches are kept in the order in which they get applied.
+
+depends/*
+  depends/rmk/devel-stable
+  depends/dma-slave/next
+  depends/v4l
+
+next/fixes-non-critical
+  omap/fixes-non-critical git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap fixes-non-critical
+  omap/fixes-hwmod git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap fixes-hwmod
+  omap/fixes-non-critical-part2 git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap fixes-non-critical-part2
+  pxa/fixes-non-critical  cherry-picked from git://github.com/hzhuang1/linux.git for-next
+
+next/cleanup
+  at91/ioremap		git://github.com/at91linux/linux-at91.git for-arnd-3.3-ioremap
+  at91/gpio		git://github.com/at91linux/linux-at91.git for-arnd-3.3-gpio
+  msm/misc		git://codeaurora.org/quic/kernel/davidb/linux-msm.git msm-misc
+  drivers/macb-gem-cleanup	parts of drivers/macb-gem that at91/gpio depends on
+  at91/defconfig	git://github.com/at91linux/linux-at91 for-arnd-3.3-defconfig
+  davinci/cleanup	git://gitorious.org/linux-davinci/linux-davinci.git cleanup
+  picoxcell/cleanup	git://github.com/jamieiles/linux-2.6-ji.git picoxcell-cleanup
+  u300/cleanup		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git u300-for-arm-soc
+  + 0363e3dae10		arm/at91: fix build of stamp9g20
+  tegra/cleanup		git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra.git for-3.3/cleanup
+
+next/dt
+  tegra/dt		git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra.git for-3.3/dt
+  samsung/dt		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-dt1
+				conflicts with depends/rmk/devel-stable
+
+next/cleanup2
+  samsung/cleanup       git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-cleanup-spi4
+				depends on samsung/dt
+                        git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-spi3
+				depends on samsung/cleanup-mmc
+                        git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-cleanup-spi4
+				depends on samsung/devel-spi
+			git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-cleanup-samsung
+
+next/soc
+  omap/soc		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap soc
+				depends on depends/rmk/devel-stable
+  tegra/soc		git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra.git for-3.3/soc
+				depends on depends/rmk/devel-stable and tegra/dt
+
+next/boards
+  samsung/board		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel
+					(cragganmore parts only)
+  tegra/boards		git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra.git for-3.3/boards
+				depends on tegra/soc
+  pxa/board		cherry-picked from git://github.com/hzhuang1/linux.git for-next
+  imx/board		git://git.pengutronix.de/git/imx/linux-2.6.git imx-features-assorted
+
+next/devel
+  highbank/devel	git://sources.calxeda.com/kernel/linux for-3.3
+  ux500/devel		git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git for-arnd
+			and:
+			git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ux500-for-arm-soc
+  omap/omap1		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap omap1
+				(depended on fixes that have gone upstream)
+  picoxcell/devel	git://github.com/jamieiles/linux-2.6-ji.git picoxcell-devel
+				(depends on picoxcell/cleanup)
+  omap/hwmod		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap hwmod
+				depends on omap/fixes-hwmod
+
+next/drivers
+  drivers/macb-gem	git://github.com/jamieiles/linux-2.6-ji.git macb-gem
+  drivers/pxa-gpio	git://github.com/hzhuang1/linux.git gpio
+				plus additional patches
+  at91/macb		git://github.com/at91linux/linux-at91.git for-arnd-3.3-driversV2
+				depends on drivers/macb-gem
+  omap/hsmmc		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap hsmmc
+  mxs/saif		git://git.linaro.org/people/shawnguo/linux-2.6.git mxs/saif-recording
+  + b17471f5d121	net: macb: fix build break with !CONFIG_OF
+  omap/ehci		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap ehci
+				depends on omap/hwmod
+  tegra/drivers		git://git.kernel.org/pub/scm/linux/kernel/git/olof/tegra.git for-3.3/drivers
+  samsung/ohci		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-ohci
+  samsung/drivers       git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-mmc-spi5
+				depends on samsung/cleanup
+  drivers/rtc-sa1100	cherry-picked from git://github.com/hzhuang1/linux.git for-next
+
+next/drivers2
+  samsung/dma		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-dma
+				depends on samsung/dt and depends/dma-slave/next
+  samsung/rtc		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-rtc
+				depends on samsung/rtc
+  at91/drivers		git://github.com/at91linux/linux-at91.git for-arnd-3.3-device_boardV2
+				depends on depends/v4l
+
+next/pm
+  omap/omap4		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap omap4
+				depends on depends/rmk/devel-stable
+  omap/prcm		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap prcm
+  omap/uart		git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap uart
+  imx6/pm		git://git.linaro.org/people/shawnguo/linux-2.6.git imx/pm
+			git://git.linaro.org/people/shawnguo/linux-2.6.git imx/pm2
+
+next/timer
+  msm/timer		git://codeaurora.org/quic/kernel/davidb/linux-msm.git msm-timer
+
+next/clk
+  imx/clk		git://git.linaro.org/people/shawnguo/linux-2.6.git mxs/clk-prepare
+
+next/move
+  imx/move		git://git.pengutronix.de/git/imx/linux-2.6.git mx5-merge
+
+late/devel
+  samsung/devel		git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next-samsung-devel-samsung
+  imx/features-assorted	git://git.pengutronix.de/git/imx/linux-2.6.git imx-features-assorted
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 81a933e..a43c758 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -24,9 +24,6 @@ config ARM_VIC_NR
 config ICST
 	bool
 
-config PL330
-	bool
-
 config SA1111
 	bool
 	select DMABOUNCE if !ARCH_PXA
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 6ea9b6f..107d6d9 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -5,7 +5,6 @@
 obj-$(CONFIG_ARM_GIC)		+= gic.o
 obj-$(CONFIG_ARM_VIC)		+= vic.o
 obj-$(CONFIG_ICST)		+= icst.o
-obj-$(CONFIG_PL330)		+= pl330.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
 obj-$(CONFIG_DMABOUNCE)		+= dmabounce.o
diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c
deleted file mode 100644
index d8e44a4..0000000
--- a/arch/arm/common/pl330.c
+++ /dev/null
@@ -1,1959 +0,0 @@
-/* linux/arch/arm/common/pl330.c
- *
- * Copyright (C) 2010 Samsung Electronics Co Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/hardware/pl330.h>
-
-/* Register and Bit field Definitions */
-#define DS		0x0
-#define DS_ST_STOP	0x0
-#define DS_ST_EXEC	0x1
-#define DS_ST_CMISS	0x2
-#define DS_ST_UPDTPC	0x3
-#define DS_ST_WFE	0x4
-#define DS_ST_ATBRR	0x5
-#define DS_ST_QBUSY	0x6
-#define DS_ST_WFP	0x7
-#define DS_ST_KILL	0x8
-#define DS_ST_CMPLT	0x9
-#define DS_ST_FLTCMP	0xe
-#define DS_ST_FAULT	0xf
-
-#define DPC		0x4
-#define INTEN		0x20
-#define ES		0x24
-#define INTSTATUS	0x28
-#define INTCLR		0x2c
-#define FSM		0x30
-#define FSC		0x34
-#define FTM		0x38
-
-#define _FTC		0x40
-#define FTC(n)		(_FTC + (n)*0x4)
-
-#define _CS		0x100
-#define CS(n)		(_CS + (n)*0x8)
-#define CS_CNS		(1 << 21)
-
-#define _CPC		0x104
-#define CPC(n)		(_CPC + (n)*0x8)
-
-#define _SA		0x400
-#define SA(n)		(_SA + (n)*0x20)
-
-#define _DA		0x404
-#define DA(n)		(_DA + (n)*0x20)
-
-#define _CC		0x408
-#define CC(n)		(_CC + (n)*0x20)
-
-#define CC_SRCINC	(1 << 0)
-#define CC_DSTINC	(1 << 14)
-#define CC_SRCPRI	(1 << 8)
-#define CC_DSTPRI	(1 << 22)
-#define CC_SRCNS	(1 << 9)
-#define CC_DSTNS	(1 << 23)
-#define CC_SRCIA	(1 << 10)
-#define CC_DSTIA	(1 << 24)
-#define CC_SRCBRSTLEN_SHFT	4
-#define CC_DSTBRSTLEN_SHFT	18
-#define CC_SRCBRSTSIZE_SHFT	1
-#define CC_DSTBRSTSIZE_SHFT	15
-#define CC_SRCCCTRL_SHFT	11
-#define CC_SRCCCTRL_MASK	0x7
-#define CC_DSTCCTRL_SHFT	25
-#define CC_DRCCCTRL_MASK	0x7
-#define CC_SWAP_SHFT	28
-
-#define _LC0		0x40c
-#define LC0(n)		(_LC0 + (n)*0x20)
-
-#define _LC1		0x410
-#define LC1(n)		(_LC1 + (n)*0x20)
-
-#define DBGSTATUS	0xd00
-#define DBG_BUSY	(1 << 0)
-
-#define DBGCMD		0xd04
-#define DBGINST0	0xd08
-#define DBGINST1	0xd0c
-
-#define CR0		0xe00
-#define CR1		0xe04
-#define CR2		0xe08
-#define CR3		0xe0c
-#define CR4		0xe10
-#define CRD		0xe14
-
-#define PERIPH_ID	0xfe0
-#define PCELL_ID	0xff0
-
-#define CR0_PERIPH_REQ_SET	(1 << 0)
-#define CR0_BOOT_EN_SET		(1 << 1)
-#define CR0_BOOT_MAN_NS		(1 << 2)
-#define CR0_NUM_CHANS_SHIFT	4
-#define CR0_NUM_CHANS_MASK	0x7
-#define CR0_NUM_PERIPH_SHIFT	12
-#define CR0_NUM_PERIPH_MASK	0x1f
-#define CR0_NUM_EVENTS_SHIFT	17
-#define CR0_NUM_EVENTS_MASK	0x1f
-
-#define CR1_ICACHE_LEN_SHIFT	0
-#define CR1_ICACHE_LEN_MASK	0x7
-#define CR1_NUM_ICACHELINES_SHIFT	4
-#define CR1_NUM_ICACHELINES_MASK	0xf
-
-#define CRD_DATA_WIDTH_SHIFT	0
-#define CRD_DATA_WIDTH_MASK	0x7
-#define CRD_WR_CAP_SHIFT	4
-#define CRD_WR_CAP_MASK		0x7
-#define CRD_WR_Q_DEP_SHIFT	8
-#define CRD_WR_Q_DEP_MASK	0xf
-#define CRD_RD_CAP_SHIFT	12
-#define CRD_RD_CAP_MASK		0x7
-#define CRD_RD_Q_DEP_SHIFT	16
-#define CRD_RD_Q_DEP_MASK	0xf
-#define CRD_DATA_BUFF_SHIFT	20
-#define CRD_DATA_BUFF_MASK	0x3ff
-
-#define	PART		0x330
-#define DESIGNER	0x41
-#define REVISION	0x0
-#define INTEG_CFG	0x0
-#define PERIPH_ID_VAL	((PART << 0) | (DESIGNER << 12))
-
-#define PCELL_ID_VAL	0xb105f00d
-
-#define PL330_STATE_STOPPED		(1 << 0)
-#define PL330_STATE_EXECUTING		(1 << 1)
-#define PL330_STATE_WFE			(1 << 2)
-#define PL330_STATE_FAULTING		(1 << 3)
-#define PL330_STATE_COMPLETING		(1 << 4)
-#define PL330_STATE_WFP			(1 << 5)
-#define PL330_STATE_KILLING		(1 << 6)
-#define PL330_STATE_FAULT_COMPLETING	(1 << 7)
-#define PL330_STATE_CACHEMISS		(1 << 8)
-#define PL330_STATE_UPDTPC		(1 << 9)
-#define PL330_STATE_ATBARRIER		(1 << 10)
-#define PL330_STATE_QUEUEBUSY		(1 << 11)
-#define PL330_STATE_INVALID		(1 << 15)
-
-#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \
-				| PL330_STATE_WFE | PL330_STATE_FAULTING)
-
-#define CMD_DMAADDH	0x54
-#define CMD_DMAEND	0x00
-#define CMD_DMAFLUSHP	0x35
-#define CMD_DMAGO	0xa0
-#define CMD_DMALD	0x04
-#define CMD_DMALDP	0x25
-#define CMD_DMALP	0x20
-#define CMD_DMALPEND	0x28
-#define CMD_DMAKILL	0x01
-#define CMD_DMAMOV	0xbc
-#define CMD_DMANOP	0x18
-#define CMD_DMARMB	0x12
-#define CMD_DMASEV	0x34
-#define CMD_DMAST	0x08
-#define CMD_DMASTP	0x29
-#define CMD_DMASTZ	0x0c
-#define CMD_DMAWFE	0x36
-#define CMD_DMAWFP	0x30
-#define CMD_DMAWMB	0x13
-
-#define SZ_DMAADDH	3
-#define SZ_DMAEND	1
-#define SZ_DMAFLUSHP	2
-#define SZ_DMALD	1
-#define SZ_DMALDP	2
-#define SZ_DMALP	2
-#define SZ_DMALPEND	2
-#define SZ_DMAKILL	1
-#define SZ_DMAMOV	6
-#define SZ_DMANOP	1
-#define SZ_DMARMB	1
-#define SZ_DMASEV	2
-#define SZ_DMAST	1
-#define SZ_DMASTP	2
-#define SZ_DMASTZ	1
-#define SZ_DMAWFE	2
-#define SZ_DMAWFP	2
-#define SZ_DMAWMB	1
-#define SZ_DMAGO	6
-
-#define BRST_LEN(ccr)	((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1)
-#define BRST_SIZE(ccr)	(1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7))
-
-#define BYTE_TO_BURST(b, ccr)  ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr))
-#define BURST_TO_BYTE(c, ccr)  ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr))
-
-/*
- * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
- * at 1byte/burst for P<->M and M<->M respectively.
- * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
- * should be enough for P<->M and M<->M respectively.
- */
-#define MCODE_BUFF_PER_REQ	256
-
-/* If the _pl330_req is available to the client */
-#define IS_FREE(req)	(*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
-
-/* Use this _only_ to wait on transient states */
-#define UNTIL(t, s)	while (!(_state(t) & (s))) cpu_relax();
-
-#ifdef PL330_DEBUG_MCGEN
-static unsigned cmd_line;
-#define PL330_DBGCMD_DUMP(off, x...)	do { \
-						printk("%x:", cmd_line); \
-						printk(x); \
-						cmd_line += off; \
-					} while (0)
-#define PL330_DBGMC_START(addr)		(cmd_line = addr)
-#else
-#define PL330_DBGCMD_DUMP(off, x...)	do {} while (0)
-#define PL330_DBGMC_START(addr)		do {} while (0)
-#endif
-
-struct _xfer_spec {
-	u32 ccr;
-	struct pl330_req *r;
-	struct pl330_xfer *x;
-};
-
-enum dmamov_dst {
-	SAR = 0,
-	CCR,
-	DAR,
-};
-
-enum pl330_dst {
-	SRC = 0,
-	DST,
-};
-
-enum pl330_cond {
-	SINGLE,
-	BURST,
-	ALWAYS,
-};
-
-struct _pl330_req {
-	u32 mc_bus;
-	void *mc_cpu;
-	/* Number of bytes taken to setup MC for the req */
-	u32 mc_len;
-	struct pl330_req *r;
-	/* Hook to attach to DMAC's list of reqs with due callback */
-	struct list_head rqd;
-};
-
-/* ToBeDone for tasklet */
-struct _pl330_tbd {
-	bool reset_dmac;
-	bool reset_mngr;
-	u8 reset_chan;
-};
-
-/* A DMAC Thread */
-struct pl330_thread {
-	u8 id;
-	int ev;
-	/* If the channel is not yet acquired by any client */
-	bool free;
-	/* Parent DMAC */
-	struct pl330_dmac *dmac;
-	/* Only two at a time */
-	struct _pl330_req req[2];
-	/* Index of the last enqueued request */
-	unsigned lstenq;
-	/* Index of the last submitted request or -1 if the DMA is stopped */
-	int req_running;
-};
-
-enum pl330_dmac_state {
-	UNINIT,
-	INIT,
-	DYING,
-};
-
-/* A DMAC */
-struct pl330_dmac {
-	spinlock_t		lock;
-	/* Holds list of reqs with due callbacks */
-	struct list_head	req_done;
-	/* Pointer to platform specific stuff */
-	struct pl330_info	*pinfo;
-	/* Maximum possible events/irqs */
-	int			events[32];
-	/* BUS address of MicroCode buffer */
-	u32			mcode_bus;
-	/* CPU address of MicroCode buffer */
-	void			*mcode_cpu;
-	/* List of all Channel threads */
-	struct pl330_thread	*channels;
-	/* Pointer to the MANAGER thread */
-	struct pl330_thread	*manager;
-	/* To handle bad news in interrupt */
-	struct tasklet_struct	tasks;
-	struct _pl330_tbd	dmac_tbd;
-	/* State of DMAC operation */
-	enum pl330_dmac_state	state;
-};
-
-static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
-{
-	if (r && r->xfer_cb)
-		r->xfer_cb(r->token, err);
-}
-
-static inline bool _queue_empty(struct pl330_thread *thrd)
-{
-	return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
-		? true : false;
-}
-
-static inline bool _queue_full(struct pl330_thread *thrd)
-{
-	return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
-		? false : true;
-}
-
-static inline bool is_manager(struct pl330_thread *thrd)
-{
-	struct pl330_dmac *pl330 = thrd->dmac;
-
-	/* MANAGER is indexed at the end */
-	if (thrd->id == pl330->pinfo->pcfg.num_chan)
-		return true;
-	else
-		return false;
-}
-
-/* If manager of the thread is in Non-Secure mode */
-static inline bool _manager_ns(struct pl330_thread *thrd)
-{
-	struct pl330_dmac *pl330 = thrd->dmac;
-
-	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
-}
-
-static inline u32 get_id(struct pl330_info *pi, u32 off)
-{
-	void __iomem *regs = pi->base;
-	u32 id = 0;
-
-	id |= (readb(regs + off + 0x0) << 0);
-	id |= (readb(regs + off + 0x4) << 8);
-	id |= (readb(regs + off + 0x8) << 16);
-	id |= (readb(regs + off + 0xc) << 24);
-
-	return id;
-}
-
-static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
-		enum pl330_dst da, u16 val)
-{
-	if (dry_run)
-		return SZ_DMAADDH;
-
-	buf[0] = CMD_DMAADDH;
-	buf[0] |= (da << 1);
-	*((u16 *)&buf[1]) = val;
-
-	PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
-		da == 1 ? "DA" : "SA", val);
-
-	return SZ_DMAADDH;
-}
-
-static inline u32 _emit_END(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMAEND;
-
-	buf[0] = CMD_DMAEND;
-
-	PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n");
-
-	return SZ_DMAEND;
-}
-
-static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri)
-{
-	if (dry_run)
-		return SZ_DMAFLUSHP;
-
-	buf[0] = CMD_DMAFLUSHP;
-
-	peri &= 0x1f;
-	peri <<= 3;
-	buf[1] = peri;
-
-	PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3);
-
-	return SZ_DMAFLUSHP;
-}
-
-static inline u32 _emit_LD(unsigned dry_run, u8 buf[],	enum pl330_cond cond)
-{
-	if (dry_run)
-		return SZ_DMALD;
-
-	buf[0] = CMD_DMALD;
-
-	if (cond == SINGLE)
-		buf[0] |= (0 << 1) | (1 << 0);
-	else if (cond == BURST)
-		buf[0] |= (1 << 1) | (1 << 0);
-
-	PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n",
-		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
-
-	return SZ_DMALD;
-}
-
-static inline u32 _emit_LDP(unsigned dry_run, u8 buf[],
-		enum pl330_cond cond, u8 peri)
-{
-	if (dry_run)
-		return SZ_DMALDP;
-
-	buf[0] = CMD_DMALDP;
-
-	if (cond == BURST)
-		buf[0] |= (1 << 1);
-
-	peri &= 0x1f;
-	peri <<= 3;
-	buf[1] = peri;
-
-	PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n",
-		cond == SINGLE ? 'S' : 'B', peri >> 3);
-
-	return SZ_DMALDP;
-}
-
-static inline u32 _emit_LP(unsigned dry_run, u8 buf[],
-		unsigned loop, u8 cnt)
-{
-	if (dry_run)
-		return SZ_DMALP;
-
-	buf[0] = CMD_DMALP;
-
-	if (loop)
-		buf[0] |= (1 << 1);
-
-	cnt--; /* DMAC increments by 1 internally */
-	buf[1] = cnt;
-
-	PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt);
-
-	return SZ_DMALP;
-}
-
-struct _arg_LPEND {
-	enum pl330_cond cond;
-	bool forever;
-	unsigned loop;
-	u8 bjump;
-};
-
-static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[],
-		const struct _arg_LPEND *arg)
-{
-	enum pl330_cond cond = arg->cond;
-	bool forever = arg->forever;
-	unsigned loop = arg->loop;
-	u8 bjump = arg->bjump;
-
-	if (dry_run)
-		return SZ_DMALPEND;
-
-	buf[0] = CMD_DMALPEND;
-
-	if (loop)
-		buf[0] |= (1 << 2);
-
-	if (!forever)
-		buf[0] |= (1 << 4);
-
-	if (cond == SINGLE)
-		buf[0] |= (0 << 1) | (1 << 0);
-	else if (cond == BURST)
-		buf[0] |= (1 << 1) | (1 << 0);
-
-	buf[1] = bjump;
-
-	PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n",
-			forever ? "FE" : "END",
-			cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'),
-			loop ? '1' : '0',
-			bjump);
-
-	return SZ_DMALPEND;
-}
-
-static inline u32 _emit_KILL(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMAKILL;
-
-	buf[0] = CMD_DMAKILL;
-
-	return SZ_DMAKILL;
-}
-
-static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
-		enum dmamov_dst dst, u32 val)
-{
-	if (dry_run)
-		return SZ_DMAMOV;
-
-	buf[0] = CMD_DMAMOV;
-	buf[1] = dst;
-	*((u32 *)&buf[2]) = val;
-
-	PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
-		dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
-
-	return SZ_DMAMOV;
-}
-
-static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMANOP;
-
-	buf[0] = CMD_DMANOP;
-
-	PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
-
-	return SZ_DMANOP;
-}
-
-static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMARMB;
-
-	buf[0] = CMD_DMARMB;
-
-	PL330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n");
-
-	return SZ_DMARMB;
-}
-
-static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev)
-{
-	if (dry_run)
-		return SZ_DMASEV;
-
-	buf[0] = CMD_DMASEV;
-
-	ev &= 0x1f;
-	ev <<= 3;
-	buf[1] = ev;
-
-	PL330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3);
-
-	return SZ_DMASEV;
-}
-
-static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum pl330_cond cond)
-{
-	if (dry_run)
-		return SZ_DMAST;
-
-	buf[0] = CMD_DMAST;
-
-	if (cond == SINGLE)
-		buf[0] |= (0 << 1) | (1 << 0);
-	else if (cond == BURST)
-		buf[0] |= (1 << 1) | (1 << 0);
-
-	PL330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n",
-		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
-
-	return SZ_DMAST;
-}
-
-static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
-		enum pl330_cond cond, u8 peri)
-{
-	if (dry_run)
-		return SZ_DMASTP;
-
-	buf[0] = CMD_DMASTP;
-
-	if (cond == BURST)
-		buf[0] |= (1 << 1);
-
-	peri &= 0x1f;
-	peri <<= 3;
-	buf[1] = peri;
-
-	PL330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n",
-		cond == SINGLE ? 'S' : 'B', peri >> 3);
-
-	return SZ_DMASTP;
-}
-
-static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMASTZ;
-
-	buf[0] = CMD_DMASTZ;
-
-	PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
-
-	return SZ_DMASTZ;
-}
-
-static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
-		unsigned invalidate)
-{
-	if (dry_run)
-		return SZ_DMAWFE;
-
-	buf[0] = CMD_DMAWFE;
-
-	ev &= 0x1f;
-	ev <<= 3;
-	buf[1] = ev;
-
-	if (invalidate)
-		buf[1] |= (1 << 1);
-
-	PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
-		ev >> 3, invalidate ? ", I" : "");
-
-	return SZ_DMAWFE;
-}
-
-static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
-		enum pl330_cond cond, u8 peri)
-{
-	if (dry_run)
-		return SZ_DMAWFP;
-
-	buf[0] = CMD_DMAWFP;
-
-	if (cond == SINGLE)
-		buf[0] |= (0 << 1) | (0 << 0);
-	else if (cond == BURST)
-		buf[0] |= (1 << 1) | (0 << 0);
-	else
-		buf[0] |= (0 << 1) | (1 << 0);
-
-	peri &= 0x1f;
-	peri <<= 3;
-	buf[1] = peri;
-
-	PL330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n",
-		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3);
-
-	return SZ_DMAWFP;
-}
-
-static inline u32 _emit_WMB(unsigned dry_run, u8 buf[])
-{
-	if (dry_run)
-		return SZ_DMAWMB;
-
-	buf[0] = CMD_DMAWMB;
-
-	PL330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n");
-
-	return SZ_DMAWMB;
-}
-
-struct _arg_GO {
-	u8 chan;
-	u32 addr;
-	unsigned ns;
-};
-
-static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
-		const struct _arg_GO *arg)
-{
-	u8 chan = arg->chan;
-	u32 addr = arg->addr;
-	unsigned ns = arg->ns;
-
-	if (dry_run)
-		return SZ_DMAGO;
-
-	buf[0] = CMD_DMAGO;
-	buf[0] |= (ns << 1);
-
-	buf[1] = chan & 0x7;
-
-	*((u32 *)&buf[2]) = addr;
-
-	return SZ_DMAGO;
-}
-
-#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
-
-/* Returns Time-Out */
-static bool _until_dmac_idle(struct pl330_thread *thrd)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	unsigned long loops = msecs_to_loops(5);
-
-	do {
-		/* Until Manager is Idle */
-		if (!(readl(regs + DBGSTATUS) & DBG_BUSY))
-			break;
-
-		cpu_relax();
-	} while (--loops);
-
-	if (!loops)
-		return true;
-
-	return false;
-}
-
-static inline void _execute_DBGINSN(struct pl330_thread *thrd,
-		u8 insn[], bool as_manager)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	u32 val;
-
-	val = (insn[0] << 16) | (insn[1] << 24);
-	if (!as_manager) {
-		val |= (1 << 0);
-		val |= (thrd->id << 8); /* Channel Number */
-	}
-	writel(val, regs + DBGINST0);
-
-	val = *((u32 *)&insn[2]);
-	writel(val, regs + DBGINST1);
-
-	/* If timed out due to halted state-machine */
-	if (_until_dmac_idle(thrd)) {
-		dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
-		return;
-	}
-
-	/* Get going */
-	writel(0, regs + DBGCMD);
-}
-
-/*
- * Mark a _pl330_req as free.
- * We do it by writing DMAEND as the first instruction
- * because no valid request is going to have DMAEND as
- * its first instruction to execute.
- */
-static void mark_free(struct pl330_thread *thrd, int idx)
-{
-	struct _pl330_req *req = &thrd->req[idx];
-
-	_emit_END(0, req->mc_cpu);
-	req->mc_len = 0;
-
-	thrd->req_running = -1;
-}
-
-static inline u32 _state(struct pl330_thread *thrd)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	u32 val;
-
-	if (is_manager(thrd))
-		val = readl(regs + DS) & 0xf;
-	else
-		val = readl(regs + CS(thrd->id)) & 0xf;
-
-	switch (val) {
-	case DS_ST_STOP:
-		return PL330_STATE_STOPPED;
-	case DS_ST_EXEC:
-		return PL330_STATE_EXECUTING;
-	case DS_ST_CMISS:
-		return PL330_STATE_CACHEMISS;
-	case DS_ST_UPDTPC:
-		return PL330_STATE_UPDTPC;
-	case DS_ST_WFE:
-		return PL330_STATE_WFE;
-	case DS_ST_FAULT:
-		return PL330_STATE_FAULTING;
-	case DS_ST_ATBRR:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_ATBARRIER;
-	case DS_ST_QBUSY:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_QUEUEBUSY;
-	case DS_ST_WFP:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_WFP;
-	case DS_ST_KILL:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_KILLING;
-	case DS_ST_CMPLT:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_COMPLETING;
-	case DS_ST_FLTCMP:
-		if (is_manager(thrd))
-			return PL330_STATE_INVALID;
-		else
-			return PL330_STATE_FAULT_COMPLETING;
-	default:
-		return PL330_STATE_INVALID;
-	}
-}
-
-static void _stop(struct pl330_thread *thrd)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	u8 insn[6] = {0, 0, 0, 0, 0, 0};
-
-	if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
-		UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
-
-	/* Return if nothing needs to be done */
-	if (_state(thrd) == PL330_STATE_COMPLETING
-		  || _state(thrd) == PL330_STATE_KILLING
-		  || _state(thrd) == PL330_STATE_STOPPED)
-		return;
-
-	_emit_KILL(0, insn);
-
-	/* Stop generating interrupts for SEV */
-	writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
-
-	_execute_DBGINSN(thrd, insn, is_manager(thrd));
-}
-
-/* Start doing req 'idx' of thread 'thrd' */
-static bool _trigger(struct pl330_thread *thrd)
-{
-	void __iomem *regs = thrd->dmac->pinfo->base;
-	struct _pl330_req *req;
-	struct pl330_req *r;
-	struct _arg_GO go;
-	unsigned ns;
-	u8 insn[6] = {0, 0, 0, 0, 0, 0};
-	int idx;
-
-	/* Return if already ACTIVE */
-	if (_state(thrd) != PL330_STATE_STOPPED)
-		return true;
-
-	idx = 1 - thrd->lstenq;
-	if (!IS_FREE(&thrd->req[idx]))
-		req = &thrd->req[idx];
-	else {
-		idx = thrd->lstenq;
-		if (!IS_FREE(&thrd->req[idx]))
-			req = &thrd->req[idx];
-		else
-			req = NULL;
-	}
-
-	/* Return if no request */
-	if (!req || !req->r)
-		return true;
-
-	r = req->r;
-
-	if (r->cfg)
-		ns = r->cfg->nonsecure ? 1 : 0;
-	else if (readl(regs + CS(thrd->id)) & CS_CNS)
-		ns = 1;
-	else
-		ns = 0;
-
-	/* See 'Abort Sources' point-4 at Page 2-25 */
-	if (_manager_ns(thrd) && !ns)
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
-			__func__, __LINE__);
-
-	go.chan = thrd->id;
-	go.addr = req->mc_bus;
-	go.ns = ns;
-	_emit_GO(0, insn, &go);
-
-	/* Set to generate interrupts for SEV */
-	writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
-
-	/* Only manager can execute GO */
-	_execute_DBGINSN(thrd, insn, true);
-
-	thrd->req_running = idx;
-
-	return true;
-}
-
-static bool _start(struct pl330_thread *thrd)
-{
-	switch (_state(thrd)) {
-	case PL330_STATE_FAULT_COMPLETING:
-		UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
-
-		if (_state(thrd) == PL330_STATE_KILLING)
-			UNTIL(thrd, PL330_STATE_STOPPED)
-
-	case PL330_STATE_FAULTING:
-		_stop(thrd);
-
-	case PL330_STATE_KILLING:
-	case PL330_STATE_COMPLETING:
-		UNTIL(thrd, PL330_STATE_STOPPED)
-
-	case PL330_STATE_STOPPED:
-		return _trigger(thrd);
-
-	case PL330_STATE_WFP:
-	case PL330_STATE_QUEUEBUSY:
-	case PL330_STATE_ATBARRIER:
-	case PL330_STATE_UPDTPC:
-	case PL330_STATE_CACHEMISS:
-	case PL330_STATE_EXECUTING:
-		return true;
-
-	case PL330_STATE_WFE: /* For RESUME, nothing yet */
-	default:
-		return false;
-	}
-}
-
-static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs, int cyc)
-{
-	int off = 0;
-
-	while (cyc--) {
-		off += _emit_LD(dry_run, &buf[off], ALWAYS);
-		off += _emit_RMB(dry_run, &buf[off]);
-		off += _emit_ST(dry_run, &buf[off], ALWAYS);
-		off += _emit_WMB(dry_run, &buf[off]);
-	}
-
-	return off;
-}
-
-static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs, int cyc)
-{
-	int off = 0;
-
-	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_ST(dry_run, &buf[off], ALWAYS);
-		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
-	}
-
-	return off;
-}
-
-static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs, int cyc)
-{
-	int off = 0;
-
-	while (cyc--) {
-		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_LD(dry_run, &buf[off], ALWAYS);
-		off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
-		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
-	}
-
-	return off;
-}
-
-static int _bursts(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs, int cyc)
-{
-	int off = 0;
-
-	switch (pxs->r->rqtype) {
-	case MEMTODEV:
-		off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
-		break;
-	case DEVTOMEM:
-		off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
-		break;
-	case MEMTOMEM:
-		off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
-		break;
-	default:
-		off += 0x40000000; /* Scare off the Client */
-		break;
-	}
-
-	return off;
-}
-
-/* Returns bytes consumed and updates bursts */
-static inline int _loop(unsigned dry_run, u8 buf[],
-		unsigned long *bursts, const struct _xfer_spec *pxs)
-{
-	int cyc, cycmax, szlp, szlpend, szbrst, off;
-	unsigned lcnt0, lcnt1, ljmp0, ljmp1;
-	struct _arg_LPEND lpend;
-
-	/* Max iterations possible in DMALP is 256 */
-	if (*bursts >= 256*256) {
-		lcnt1 = 256;
-		lcnt0 = 256;
-		cyc = *bursts / lcnt1 / lcnt0;
-	} else if (*bursts > 256) {
-		lcnt1 = 256;
-		lcnt0 = *bursts / lcnt1;
-		cyc = 1;
-	} else {
-		lcnt1 = *bursts;
-		lcnt0 = 0;
-		cyc = 1;
-	}
-
-	szlp = _emit_LP(1, buf, 0, 0);
-	szbrst = _bursts(1, buf, pxs, 1);
-
-	lpend.cond = ALWAYS;
-	lpend.forever = false;
-	lpend.loop = 0;
-	lpend.bjump = 0;
-	szlpend = _emit_LPEND(1, buf, &lpend);
-
-	if (lcnt0) {
-		szlp *= 2;
-		szlpend *= 2;
-	}
-
-	/*
-	 * Max bursts that we can unroll due to limit on the
-	 * size of backward jump that can be encoded in DMALPEND
-	 * which is 8-bits and hence 255
-	 */
-	cycmax = (255 - (szlp + szlpend)) / szbrst;
-
-	cyc = (cycmax < cyc) ? cycmax : cyc;
-
-	off = 0;
-
-	if (lcnt0) {
-		off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
-		ljmp0 = off;
-	}
-
-	off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
-	ljmp1 = off;
-
-	off += _bursts(dry_run, &buf[off], pxs, cyc);
-
-	lpend.cond = ALWAYS;
-	lpend.forever = false;
-	lpend.loop = 1;
-	lpend.bjump = off - ljmp1;
-	off += _emit_LPEND(dry_run, &buf[off], &lpend);
-
-	if (lcnt0) {
-		lpend.cond = ALWAYS;
-		lpend.forever = false;
-		lpend.loop = 0;
-		lpend.bjump = off - ljmp0;
-		off += _emit_LPEND(dry_run, &buf[off], &lpend);
-	}
-
-	*bursts = lcnt1 * cyc;
-	if (lcnt0)
-		*bursts *= lcnt0;
-
-	return off;
-}
-
-static inline int _setup_loops(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs)
-{
-	struct pl330_xfer *x = pxs->x;
-	u32 ccr = pxs->ccr;
-	unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
-	int off = 0;
-
-	while (bursts) {
-		c = bursts;
-		off += _loop(dry_run, &buf[off], &c, pxs);
-		bursts -= c;
-	}
-
-	return off;
-}
-
-static inline int _setup_xfer(unsigned dry_run, u8 buf[],
-		const struct _xfer_spec *pxs)
-{
-	struct pl330_xfer *x = pxs->x;
-	int off = 0;
-
-	/* DMAMOV SAR, x->src_addr */
-	off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
-	/* DMAMOV DAR, x->dst_addr */
-	off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
-
-	/* Setup Loop(s) */
-	off += _setup_loops(dry_run, &buf[off], pxs);
-
-	return off;
-}
-
-/*
- * A req is a sequence of one or more xfer units.
- * Returns the number of bytes taken to setup the MC for the req.
- */
-static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
-		unsigned index, struct _xfer_spec *pxs)
-{
-	struct _pl330_req *req = &thrd->req[index];
-	struct pl330_xfer *x;
-	u8 *buf = req->mc_cpu;
-	int off = 0;
-
-	PL330_DBGMC_START(req->mc_bus);
-
-	/* DMAMOV CCR, ccr */
-	off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
-
-	x = pxs->r->x;
-	do {
-		/* Error if xfer length is not aligned at burst size */
-		if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
-			return -EINVAL;
-
-		pxs->x = x;
-		off += _setup_xfer(dry_run, &buf[off], pxs);
-
-		x = x->next;
-	} while (x);
-
-	/* DMASEV peripheral/event */
-	off += _emit_SEV(dry_run, &buf[off], thrd->ev);
-	/* DMAEND */
-	off += _emit_END(dry_run, &buf[off]);
-
-	return off;
-}
-
-static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
-{
-	u32 ccr = 0;
-
-	if (rqc->src_inc)
-		ccr |= CC_SRCINC;
-
-	if (rqc->dst_inc)
-		ccr |= CC_DSTINC;
-
-	/* We set same protection levels for Src and DST for now */
-	if (rqc->privileged)
-		ccr |= CC_SRCPRI | CC_DSTPRI;
-	if (rqc->nonsecure)
-		ccr |= CC_SRCNS | CC_DSTNS;
-	if (rqc->insnaccess)
-		ccr |= CC_SRCIA | CC_DSTIA;
-
-	ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT);
-	ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT);
-
-	ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
-	ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
-
-	ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
-	ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
-
-	ccr |= (rqc->swap << CC_SWAP_SHFT);
-
-	return ccr;
-}
-
-static inline bool _is_valid(u32 ccr)
-{
-	enum pl330_dstcachectrl dcctl;
-	enum pl330_srccachectrl scctl;
-
-	dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
-	scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
-
-	if (dcctl == DINVALID1 || dcctl == DINVALID2
-			|| scctl == SINVALID1 || scctl == SINVALID2)
-		return false;
-	else
-		return true;
-}
-
-/*
- * Submit a list of xfers after which the client wants notification.
- * Client is not notified after each xfer unit, just once after all
- * xfer units are done or some error occurs.
- */
-int pl330_submit_req(void *ch_id, struct pl330_req *r)
-{
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	struct pl330_info *pi;
-	struct _xfer_spec xs;
-	unsigned long flags;
-	void __iomem *regs;
-	unsigned idx;
-	u32 ccr;
-	int ret = 0;
-
-	/* No Req or Unacquired Channel or DMAC */
-	if (!r || !thrd || thrd->free)
-		return -EINVAL;
-
-	pl330 = thrd->dmac;
-	pi = pl330->pinfo;
-	regs = pi->base;
-
-	if (pl330->state == DYING
-		|| pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
-			__func__, __LINE__);
-		return -EAGAIN;
-	}
-
-	/* If request for non-existing peripheral */
-	if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
-		dev_info(thrd->dmac->pinfo->dev,
-				"%s:%d Invalid peripheral(%u)!\n",
-				__func__, __LINE__, r->peri);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	if (_queue_full(thrd)) {
-		ret = -EAGAIN;
-		goto xfer_exit;
-	}
-
-	/* Prefer Secure Channel */
-	if (!_manager_ns(thrd))
-		r->cfg->nonsecure = 0;
-	else
-		r->cfg->nonsecure = 1;
-
-	/* Use last settings, if not provided */
-	if (r->cfg)
-		ccr = _prepare_ccr(r->cfg);
-	else
-		ccr = readl(regs + CC(thrd->id));
-
-	/* If this req doesn't have valid xfer settings */
-	if (!_is_valid(ccr)) {
-		ret = -EINVAL;
-		dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
-			__func__, __LINE__, ccr);
-		goto xfer_exit;
-	}
-
-	idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
-
-	xs.ccr = ccr;
-	xs.r = r;
-
-	/* First dry run to check if req is acceptable */
-	ret = _setup_req(1, thrd, idx, &xs);
-	if (ret < 0)
-		goto xfer_exit;
-
-	if (ret > pi->mcbufsz / 2) {
-		dev_info(thrd->dmac->pinfo->dev,
-			"%s:%d Trying increasing mcbufsz\n",
-				__func__, __LINE__);
-		ret = -ENOMEM;
-		goto xfer_exit;
-	}
-
-	/* Hook the request */
-	thrd->lstenq = idx;
-	thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
-	thrd->req[idx].r = r;
-
-	ret = 0;
-
-xfer_exit:
-	spin_unlock_irqrestore(&pl330->lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(pl330_submit_req);
-
-static void pl330_dotask(unsigned long data)
-{
-	struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
-	struct pl330_info *pi = pl330->pinfo;
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	/* The DMAC itself gone nuts */
-	if (pl330->dmac_tbd.reset_dmac) {
-		pl330->state = DYING;
-		/* Reset the manager too */
-		pl330->dmac_tbd.reset_mngr = true;
-		/* Clear the reset flag */
-		pl330->dmac_tbd.reset_dmac = false;
-	}
-
-	if (pl330->dmac_tbd.reset_mngr) {
-		_stop(pl330->manager);
-		/* Reset all channels */
-		pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
-		/* Clear the reset flag */
-		pl330->dmac_tbd.reset_mngr = false;
-	}
-
-	for (i = 0; i < pi->pcfg.num_chan; i++) {
-
-		if (pl330->dmac_tbd.reset_chan & (1 << i)) {
-			struct pl330_thread *thrd = &pl330->channels[i];
-			void __iomem *regs = pi->base;
-			enum pl330_op_err err;
-
-			_stop(thrd);
-
-			if (readl(regs + FSC) & (1 << thrd->id))
-				err = PL330_ERR_FAIL;
-			else
-				err = PL330_ERR_ABORT;
-
-			spin_unlock_irqrestore(&pl330->lock, flags);
-
-			_callback(thrd->req[1 - thrd->lstenq].r, err);
-			_callback(thrd->req[thrd->lstenq].r, err);
-
-			spin_lock_irqsave(&pl330->lock, flags);
-
-			thrd->req[0].r = NULL;
-			thrd->req[1].r = NULL;
-			mark_free(thrd, 0);
-			mark_free(thrd, 1);
-
-			/* Clear the reset flag */
-			pl330->dmac_tbd.reset_chan &= ~(1 << i);
-		}
-	}
-
-	spin_unlock_irqrestore(&pl330->lock, flags);
-
-	return;
-}
-
-/* Returns 1 if state was updated, 0 otherwise */
-int pl330_update(const struct pl330_info *pi)
-{
-	struct _pl330_req *rqdone;
-	struct pl330_dmac *pl330;
-	unsigned long flags;
-	void __iomem *regs;
-	u32 val;
-	int id, ev, ret = 0;
-
-	if (!pi || !pi->pl330_data)
-		return 0;
-
-	regs = pi->base;
-	pl330 = pi->pl330_data;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	val = readl(regs + FSM) & 0x1;
-	if (val)
-		pl330->dmac_tbd.reset_mngr = true;
-	else
-		pl330->dmac_tbd.reset_mngr = false;
-
-	val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
-	pl330->dmac_tbd.reset_chan |= val;
-	if (val) {
-		int i = 0;
-		while (i < pi->pcfg.num_chan) {
-			if (val & (1 << i)) {
-				dev_info(pi->dev,
-					"Reset Channel-%d\t CS-%x FTC-%x\n",
-						i, readl(regs + CS(i)),
-						readl(regs + FTC(i)));
-				_stop(&pl330->channels[i]);
-			}
-			i++;
-		}
-	}
-
-	/* Check which event happened i.e, thread notified */
-	val = readl(regs + ES);
-	if (pi->pcfg.num_events < 32
-			&& val & ~((1 << pi->pcfg.num_events) - 1)) {
-		pl330->dmac_tbd.reset_dmac = true;
-		dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
-		ret = 1;
-		goto updt_exit;
-	}
-
-	for (ev = 0; ev < pi->pcfg.num_events; ev++) {
-		if (val & (1 << ev)) { /* Event occurred */
-			struct pl330_thread *thrd;
-			u32 inten = readl(regs + INTEN);
-			int active;
-
-			/* Clear the event */
-			if (inten & (1 << ev))
-				writel(1 << ev, regs + INTCLR);
-
-			ret = 1;
-
-			id = pl330->events[ev];
-
-			thrd = &pl330->channels[id];
-
-			active = thrd->req_running;
-			if (active == -1) /* Aborted */
-				continue;
-
-			rqdone = &thrd->req[active];
-			mark_free(thrd, active);
-
-			/* Get going again ASAP */
-			_start(thrd);
-
-			/* For now, just make a list of callbacks to be done */
-			list_add_tail(&rqdone->rqd, &pl330->req_done);
-		}
-	}
-
-	/* Now that we are in no hurry, do the callbacks */
-	while (!list_empty(&pl330->req_done)) {
-		struct pl330_req *r;
-
-		rqdone = container_of(pl330->req_done.next,
-					struct _pl330_req, rqd);
-
-		list_del_init(&rqdone->rqd);
-
-		/* Detach the req */
-		r = rqdone->r;
-		rqdone->r = NULL;
-
-		spin_unlock_irqrestore(&pl330->lock, flags);
-		_callback(r, PL330_ERR_NONE);
-		spin_lock_irqsave(&pl330->lock, flags);
-	}
-
-updt_exit:
-	spin_unlock_irqrestore(&pl330->lock, flags);
-
-	if (pl330->dmac_tbd.reset_dmac
-			|| pl330->dmac_tbd.reset_mngr
-			|| pl330->dmac_tbd.reset_chan) {
-		ret = 1;
-		tasklet_schedule(&pl330->tasks);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(pl330_update);
-
-int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
-{
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	unsigned long flags;
-	int ret = 0, active = thrd->req_running;
-
-	if (!thrd || thrd->free || thrd->dmac->state == DYING)
-		return -EINVAL;
-
-	pl330 = thrd->dmac;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	switch (op) {
-	case PL330_OP_FLUSH:
-		/* Make sure the channel is stopped */
-		_stop(thrd);
-
-		thrd->req[0].r = NULL;
-		thrd->req[1].r = NULL;
-		mark_free(thrd, 0);
-		mark_free(thrd, 1);
-		break;
-
-	case PL330_OP_ABORT:
-		/* Make sure the channel is stopped */
-		_stop(thrd);
-
-		/* ABORT is only for the active req */
-		if (active == -1)
-			break;
-
-		thrd->req[active].r = NULL;
-		mark_free(thrd, active);
-
-		/* Start the next */
-	case PL330_OP_START:
-		if ((active == -1) && !_start(thrd))
-			ret = -EIO;
-		break;
-
-	default:
-		ret = -EINVAL;
-	}
-
-	spin_unlock_irqrestore(&pl330->lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(pl330_chan_ctrl);
-
-int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus)
-{
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	struct pl330_info *pi;
-	void __iomem *regs;
-	int active;
-	u32 val;
-
-	if (!pstatus || !thrd || thrd->free)
-		return -EINVAL;
-
-	pl330 = thrd->dmac;
-	pi = pl330->pinfo;
-	regs = pi->base;
-
-	/* The client should remove the DMAC and add again */
-	if (pl330->state == DYING)
-		pstatus->dmac_halted = true;
-	else
-		pstatus->dmac_halted = false;
-
-	val = readl(regs + FSC);
-	if (val & (1 << thrd->id))
-		pstatus->faulting = true;
-	else
-		pstatus->faulting = false;
-
-	active = thrd->req_running;
-
-	if (active == -1) {
-		/* Indicate that the thread is not running */
-		pstatus->top_req = NULL;
-		pstatus->wait_req = NULL;
-	} else {
-		pstatus->top_req = thrd->req[active].r;
-		pstatus->wait_req = !IS_FREE(&thrd->req[1 - active])
-					? thrd->req[1 - active].r : NULL;
-	}
-
-	pstatus->src_addr = readl(regs + SA(thrd->id));
-	pstatus->dst_addr = readl(regs + DA(thrd->id));
-
-	return 0;
-}
-EXPORT_SYMBOL(pl330_chan_status);
-
-/* Reserve an event */
-static inline int _alloc_event(struct pl330_thread *thrd)
-{
-	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
-	int ev;
-
-	for (ev = 0; ev < pi->pcfg.num_events; ev++)
-		if (pl330->events[ev] == -1) {
-			pl330->events[ev] = thrd->id;
-			return ev;
-		}
-
-	return -1;
-}
-
-static bool _chan_ns(const struct pl330_info *pi, int i)
-{
-	return pi->pcfg.irq_ns & (1 << i);
-}
-
-/* Upon success, returns IdentityToken for the
- * allocated channel, NULL otherwise.
- */
-void *pl330_request_channel(const struct pl330_info *pi)
-{
-	struct pl330_thread *thrd = NULL;
-	struct pl330_dmac *pl330;
-	unsigned long flags;
-	int chans, i;
-
-	if (!pi || !pi->pl330_data)
-		return NULL;
-
-	pl330 = pi->pl330_data;
-
-	if (pl330->state == DYING)
-		return NULL;
-
-	chans = pi->pcfg.num_chan;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-
-	for (i = 0; i < chans; i++) {
-		thrd = &pl330->channels[i];
-		if ((thrd->free) && (!_manager_ns(thrd) ||
-					_chan_ns(pi, i))) {
-			thrd->ev = _alloc_event(thrd);
-			if (thrd->ev >= 0) {
-				thrd->free = false;
-				thrd->lstenq = 1;
-				thrd->req[0].r = NULL;
-				mark_free(thrd, 0);
-				thrd->req[1].r = NULL;
-				mark_free(thrd, 1);
-				break;
-			}
-		}
-		thrd = NULL;
-	}
-
-	spin_unlock_irqrestore(&pl330->lock, flags);
-
-	return thrd;
-}
-EXPORT_SYMBOL(pl330_request_channel);
-
-/* Release an event */
-static inline void _free_event(struct pl330_thread *thrd, int ev)
-{
-	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
-
-	/* If the event is valid and was held by the thread */
-	if (ev >= 0 && ev < pi->pcfg.num_events
-			&& pl330->events[ev] == thrd->id)
-		pl330->events[ev] = -1;
-}
-
-void pl330_release_channel(void *ch_id)
-{
-	struct pl330_thread *thrd = ch_id;
-	struct pl330_dmac *pl330;
-	unsigned long flags;
-
-	if (!thrd || thrd->free)
-		return;
-
-	_stop(thrd);
-
-	_callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
-	_callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
-
-	pl330 = thrd->dmac;
-
-	spin_lock_irqsave(&pl330->lock, flags);
-	_free_event(thrd, thrd->ev);
-	thrd->free = true;
-	spin_unlock_irqrestore(&pl330->lock, flags);
-}
-EXPORT_SYMBOL(pl330_release_channel);
-
-/* Initialize the structure for PL330 configuration, that can be used
- * by the client driver the make best use of the DMAC
- */
-static void read_dmac_config(struct pl330_info *pi)
-{
-	void __iomem *regs = pi->base;
-	u32 val;
-
-	val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
-	val &= CRD_DATA_WIDTH_MASK;
-	pi->pcfg.data_bus_width = 8 * (1 << val);
-
-	val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
-	val &= CRD_DATA_BUFF_MASK;
-	pi->pcfg.data_buf_dep = val + 1;
-
-	val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
-	val &= CR0_NUM_CHANS_MASK;
-	val += 1;
-	pi->pcfg.num_chan = val;
-
-	val = readl(regs + CR0);
-	if (val & CR0_PERIPH_REQ_SET) {
-		val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
-		val += 1;
-		pi->pcfg.num_peri = val;
-		pi->pcfg.peri_ns = readl(regs + CR4);
-	} else {
-		pi->pcfg.num_peri = 0;
-	}
-
-	val = readl(regs + CR0);
-	if (val & CR0_BOOT_MAN_NS)
-		pi->pcfg.mode |= DMAC_MODE_NS;
-	else
-		pi->pcfg.mode &= ~DMAC_MODE_NS;
-
-	val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
-	val &= CR0_NUM_EVENTS_MASK;
-	val += 1;
-	pi->pcfg.num_events = val;
-
-	pi->pcfg.irq_ns = readl(regs + CR3);
-
-	pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
-	pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
-}
-
-static inline void _reset_thread(struct pl330_thread *thrd)
-{
-	struct pl330_dmac *pl330 = thrd->dmac;
-	struct pl330_info *pi = pl330->pinfo;
-
-	thrd->req[0].mc_cpu = pl330->mcode_cpu
-				+ (thrd->id * pi->mcbufsz);
-	thrd->req[0].mc_bus = pl330->mcode_bus
-				+ (thrd->id * pi->mcbufsz);
-	thrd->req[0].r = NULL;
-	mark_free(thrd, 0);
-
-	thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
-				+ pi->mcbufsz / 2;
-	thrd->req[1].mc_bus = thrd->req[0].mc_bus
-				+ pi->mcbufsz / 2;
-	thrd->req[1].r = NULL;
-	mark_free(thrd, 1);
-}
-
-static int dmac_alloc_threads(struct pl330_dmac *pl330)
-{
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
-	struct pl330_thread *thrd;
-	int i;
-
-	/* Allocate 1 Manager and 'chans' Channel threads */
-	pl330->channels = kzalloc((1 + chans) * sizeof(*thrd),
-					GFP_KERNEL);
-	if (!pl330->channels)
-		return -ENOMEM;
-
-	/* Init Channel threads */
-	for (i = 0; i < chans; i++) {
-		thrd = &pl330->channels[i];
-		thrd->id = i;
-		thrd->dmac = pl330;
-		_reset_thread(thrd);
-		thrd->free = true;
-	}
-
-	/* MANAGER is indexed at the end */
-	thrd = &pl330->channels[chans];
-	thrd->id = chans;
-	thrd->dmac = pl330;
-	thrd->free = false;
-	pl330->manager = thrd;
-
-	return 0;
-}
-
-static int dmac_alloc_resources(struct pl330_dmac *pl330)
-{
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
-	int ret;
-
-	/*
-	 * Alloc MicroCode buffer for 'chans' Channel threads.
-	 * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
-	 */
-	pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
-				chans * pi->mcbufsz,
-				&pl330->mcode_bus, GFP_KERNEL);
-	if (!pl330->mcode_cpu) {
-		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
-			__func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	ret = dmac_alloc_threads(pl330);
-	if (ret) {
-		dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
-			__func__, __LINE__);
-		dma_free_coherent(pi->dev,
-				chans * pi->mcbufsz,
-				pl330->mcode_cpu, pl330->mcode_bus);
-		return ret;
-	}
-
-	return 0;
-}
-
-int pl330_add(struct pl330_info *pi)
-{
-	struct pl330_dmac *pl330;
-	void __iomem *regs;
-	int i, ret;
-
-	if (!pi || !pi->dev)
-		return -EINVAL;
-
-	/* If already added */
-	if (pi->pl330_data)
-		return -EINVAL;
-
-	/*
-	 * If the SoC can perform reset on the DMAC, then do it
-	 * before reading its configuration.
-	 */
-	if (pi->dmac_reset)
-		pi->dmac_reset(pi);
-
-	regs = pi->base;
-
-	/* Check if we can handle this DMAC */
-	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
-	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
-		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
-			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
-		return -EINVAL;
-	}
-
-	/* Read the configuration of the DMAC */
-	read_dmac_config(pi);
-
-	if (pi->pcfg.num_events == 0) {
-		dev_err(pi->dev, "%s:%d Can't work without events!\n",
-			__func__, __LINE__);
-		return -EINVAL;
-	}
-
-	pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
-	if (!pl330) {
-		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
-			__func__, __LINE__);
-		return -ENOMEM;
-	}
-
-	/* Assign the info structure and private data */
-	pl330->pinfo = pi;
-	pi->pl330_data = pl330;
-
-	spin_lock_init(&pl330->lock);
-
-	INIT_LIST_HEAD(&pl330->req_done);
-
-	/* Use default MC buffer size if not provided */
-	if (!pi->mcbufsz)
-		pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
-
-	/* Mark all events as free */
-	for (i = 0; i < pi->pcfg.num_events; i++)
-		pl330->events[i] = -1;
-
-	/* Allocate resources needed by the DMAC */
-	ret = dmac_alloc_resources(pl330);
-	if (ret) {
-		dev_err(pi->dev, "Unable to create channels for DMAC\n");
-		kfree(pl330);
-		return ret;
-	}
-
-	tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330);
-
-	pl330->state = INIT;
-
-	return 0;
-}
-EXPORT_SYMBOL(pl330_add);
-
-static int dmac_free_threads(struct pl330_dmac *pl330)
-{
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
-	struct pl330_thread *thrd;
-	int i;
-
-	/* Release Channel threads */
-	for (i = 0; i < chans; i++) {
-		thrd = &pl330->channels[i];
-		pl330_release_channel((void *)thrd);
-	}
-
-	/* Free memory */
-	kfree(pl330->channels);
-
-	return 0;
-}
-
-static void dmac_free_resources(struct pl330_dmac *pl330)
-{
-	struct pl330_info *pi = pl330->pinfo;
-	int chans = pi->pcfg.num_chan;
-
-	dmac_free_threads(pl330);
-
-	dma_free_coherent(pi->dev, chans * pi->mcbufsz,
-				pl330->mcode_cpu, pl330->mcode_bus);
-}
-
-void pl330_del(struct pl330_info *pi)
-{
-	struct pl330_dmac *pl330;
-
-	if (!pi || !pi->pl330_data)
-		return;
-
-	pl330 = pi->pl330_data;
-
-	pl330->state = UNINIT;
-
-	tasklet_kill(&pl330->tasks);
-
-	/* Free DMAC resources */
-	dmac_free_resources(pl330);
-
-	kfree(pl330);
-	pi->pl330_data = NULL;
-}
-EXPORT_SYMBOL(pl330_del);
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
new file mode 100644
index 0000000..3a4fb2e
--- /dev/null
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -0,0 +1,193 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUPS=y
+CONFIG_RELAY=y
+CONFIG_EXPERT=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_MXC=y
+CONFIG_MACH_MX31LILLY=y
+CONFIG_MACH_MX31LITE=y
+CONFIG_MACH_PCM037=y
+CONFIG_MACH_PCM037_EET=y
+CONFIG_MACH_MX31_3DS=y
+CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_QONG=y
+CONFIG_MACH_ARMADILLO5X0=y
+CONFIG_MACH_KZM_ARM11_01=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_MX35_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX35=y
+CONFIG_MACH_VPR200=y
+CONFIG_MACH_IMX51_DT=y
+CONFIG_MACH_MX51_3DS=y
+CONFIG_MACH_EUKREA_CPUIMX51=y
+CONFIG_MACH_EUKREA_CPUIMX51SD=y
+CONFIG_MACH_MX51_EFIKAMX=y
+CONFIG_MACH_MX51_EFIKASB=y
+CONFIG_MACH_IMX53_DT=y
+CONFIG_SOC_IMX6Q=y
+CONFIG_MXC_PWM=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=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_IPV6=y
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
+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_FEC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_MMA8450=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_HW_RANDOM=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
+CONFIG_SPI=y
+CONFIG_SPI_IMX=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_IMX2_WDT=y
+CONFIG_MFD_MC13XXX=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MC13892=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_MXC=y
+CONFIG_DMADEVICES=y
+CONFIG_IMX_SDMA=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_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_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CONFIGFS_FS=m
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FTRACE is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_SECURITYFS=y
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=m
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=m
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
diff --git a/arch/arm/configs/mx3_defconfig b/arch/arm/configs/mx3_defconfig
deleted file mode 100644
index cb0717f..0000000
--- a/arch/arm/configs/mx3_defconfig
+++ /dev/null
@@ -1,144 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_MACH_MX31ADS_WM1133_EV1=y
-CONFIG_MACH_MX31LILLY=y
-CONFIG_MACH_MX31LITE=y
-CONFIG_MACH_PCM037=y
-CONFIG_MACH_PCM037_EET=y
-CONFIG_MACH_MX31_3DS=y
-CONFIG_MACH_MX31MOBOARD=y
-CONFIG_MACH_QONG=y
-CONFIG_MACH_ARMADILLO5X0=y
-CONFIG_MACH_KZM_ARM11_01=y
-CONFIG_MACH_PCM043=y
-CONFIG_MACH_MX35_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX35=y
-CONFIG_MXC_IRQ_PRIOR=y
-CONFIG_MXC_PWM=y
-CONFIG_ARM_ERRATA_411920=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-CONFIG_VFP=y
-CONFIG_PM_DEBUG=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_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_FW_LOADER=m
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_MXC=y
-CONFIG_MTD_UBI=y
-# CONFIG_BLK_DEV is not set
-CONFIG_MISC_DEVICES=y
-CONFIG_EEPROM_AT24=y
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMSC911X=y
-CONFIG_DNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_IMX=y
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_8250=m
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_IMX=y
-CONFIG_SPI=y
-CONFIG_W1=y
-CONFIG_W1_MASTER_MXC=y
-CONFIG_W1_SLAVE_THERM=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_WM8350_I2C=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_WM8350=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_SOC_CAMERA=y
-CONFIG_SOC_CAMERA_MT9M001=y
-CONFIG_SOC_CAMERA_MT9M111=y
-CONFIG_SOC_CAMERA_MT9T031=y
-CONFIG_SOC_CAMERA_MT9V022=y
-CONFIG_SOC_CAMERA_TW9910=y
-CONFIG_SOC_CAMERA_OV772X=y
-CONFIG_VIDEO_MX3=y
-# CONFIG_RADIO_ADAPTERS is not set
-CONFIG_FB=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_IMX_SOC=y
-CONFIG_SND_MXC_SOC_WM1133_EV1=y
-CONFIG_SND_SOC_PHYCORE_AC97=y
-CONFIG_SND_SOC_EUKREA_TLV320=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_GADGET=m
-CONFIG_USB_FSL_USB2=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_USB_ULPI=y
-CONFIG_MMC=y
-CONFIG_MMC_MXC=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_MXC=y
-CONFIG_DMADEVICES=y
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_UBIFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/arm/configs/mx5_defconfig b/arch/arm/configs/mx5_defconfig
deleted file mode 100644
index d0d8dfe..0000000
--- a/arch/arm/configs/mx5_defconfig
+++ /dev/null
@@ -1,184 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_KERNEL_LZO=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=18
-CONFIG_RELAY=y
-CONFIG_EXPERT=y
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_MXC=y
-CONFIG_ARCH_MX5=y
-CONFIG_MACH_MX51_BABBAGE=y
-CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
-CONFIG_MACH_EUKREA_CPUIMX51SD=y
-CONFIG_MACH_MX51_EFIKAMX=y
-CONFIG_MACH_MX51_EFIKASB=y
-CONFIG_MACH_MX53_EVK=y
-CONFIG_MACH_MX53_SMD=y
-CONFIG_MACH_MX53_LOCO=y
-CONFIG_MACH_MX53_ARD=y
-CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_VMSPLIT_2G=y
-CONFIG_PREEMPT_VOLUNTARY=y
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=m
-CONFIG_PM_DEBUG=y
-CONFIG_PM_TEST_SUSPEND=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_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_ATA=y
-CONFIG_PATA_IMX=y
-CONFIG_NETDEVICES=y
-CONFIG_MII=m
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_ICPLUS_PHY=y
-CONFIG_REALTEK_PHY=y
-CONFIG_NATIONAL_PHY=y
-CONFIG_STE10XP=y
-CONFIG_LSI_ET1011C_PHY=y
-CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=m
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_PS2_ELANTECH=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_MMA8450=y
-CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_HW_RANDOM=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
-CONFIG_SPI=y
-CONFIG_SPI_IMX=y
-CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_MC13892=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MXC=y
-CONFIG_USB_STORAGE=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=m
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_ESDHC_IMX=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_RTC_MXC=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_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_QUOTA=y
-CONFIG_QUOTA_NETLINK_INTERFACE=y
-# CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_DEFAULT="cp437"
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=m
-CONFIG_NLS_UTF8=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_LZO=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-# CONFIG_CRYPTO_HW is not set
-CONFIG_CRC_CCITT=m
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC7=m
-CONFIG_LIBCRC32C=m
diff --git a/arch/arm/include/asm/hardware/pl330.h b/arch/arm/include/asm/hardware/pl330.h
index 575fa81..1f4d7cb 100644
--- a/arch/arm/include/asm/hardware/pl330.h
+++ b/arch/arm/include/asm/hardware/pl330.h
@@ -47,42 +47,6 @@ enum pl330_dstcachectrl {
 	DCCTRL7, /* Cacheable write-back, allocate on writes only */
 };
 
-/* Populated by the PL330 core driver for DMA API driver's info */
-struct pl330_config {
-	u32	periph_id;
-	u32	pcell_id;
-#define DMAC_MODE_NS	(1 << 0)
-	unsigned int	mode;
-	unsigned int	data_bus_width:10; /* In number of bits */
-	unsigned int	data_buf_dep:10;
-	unsigned int	num_chan:4;
-	unsigned int	num_peri:6;
-	u32		peri_ns;
-	unsigned int	num_events:6;
-	u32		irq_ns;
-};
-
-/* Handle to the DMAC provided to the PL330 core */
-struct pl330_info {
-	/* Owning device */
-	struct device *dev;
-	/* Size of MicroCode buffers for each channel. */
-	unsigned mcbufsz;
-	/* ioremap'ed address of PL330 registers. */
-	void __iomem	*base;
-	/* Client can freely use it. */
-	void	*client_data;
-	/* PL330 core data, Client must not touch it. */
-	void	*pl330_data;
-	/* Populated by the PL330 core driver during pl330_add */
-	struct pl330_config	pcfg;
-	/*
-	 * If the DMAC has some reset mechanism, then the
-	 * client may want to provide pointer to the method.
-	 */
-	void (*dmac_reset)(struct pl330_info *pi);
-};
-
 enum pl330_byteswap {
 	SWAP_NO = 0,
 	SWAP_2,
@@ -91,60 +55,6 @@ enum pl330_byteswap {
 	SWAP_16,
 };
 
-/**
- * Request Configuration.
- * The PL330 core does not modify this and uses the last
- * working configuration if the request doesn't provide any.
- *
- * The Client may want to provide this info only for the
- * first request and a request with new settings.
- */
-struct pl330_reqcfg {
-	/* Address Incrementing */
-	unsigned dst_inc:1;
-	unsigned src_inc:1;
-
-	/*
-	 * For now, the SRC & DST protection levels
-	 * and burst size/length are assumed same.
-	 */
-	bool nonsecure;
-	bool privileged;
-	bool insnaccess;
-	unsigned brst_len:5;
-	unsigned brst_size:3; /* in power of 2 */
-
-	enum pl330_dstcachectrl dcctl;
-	enum pl330_srccachectrl scctl;
-	enum pl330_byteswap swap;
-};
-
-/*
- * One cycle of DMAC operation.
- * There may be more than one xfer in a request.
- */
-struct pl330_xfer {
-	u32 src_addr;
-	u32 dst_addr;
-	/* Size to xfer */
-	u32 bytes;
-	/*
-	 * Pointer to next xfer in the list.
-	 * The last xfer in the req must point to NULL.
-	 */
-	struct pl330_xfer *next;
-};
-
-/* The xfer callbacks are made with one of these arguments. */
-enum pl330_op_err {
-	/* The all xfers in the request were success. */
-	PL330_ERR_NONE,
-	/* If req aborted due to global error. */
-	PL330_ERR_ABORT,
-	/* If req failed due to problem with Channel. */
-	PL330_ERR_FAIL,
-};
-
 enum pl330_reqtype {
 	MEMTOMEM,
 	MEMTODEV,
@@ -152,66 +62,192 @@ enum pl330_reqtype {
 	DEVTODEV,
 };
 
-/* A request defining Scatter-Gather List ending with NULL xfer. */
-struct pl330_req {
-	enum pl330_reqtype rqtype;
-	/* Index of peripheral for the xfer. */
-	unsigned peri:5;
-	/* Unique token for this xfer, set by the client. */
-	void *token;
-	/* Callback to be called after xfer. */
-	void (*xfer_cb)(void *token, enum pl330_op_err err);
-	/* If NULL, req will be done at last set parameters. */
-	struct pl330_reqcfg *cfg;
-	/* Pointer to first xfer in the request. */
-	struct pl330_xfer *x;
-};
-
-/*
- * To know the status of the channel and DMAC, the client
- * provides a pointer to this structure. The PL330 core
- * fills it with current information.
- */
-struct pl330_chanstatus {
-	/*
-	 * If the DMAC engine halted due to some error,
-	 * the client should remove-add DMAC.
-	 */
-	bool dmac_halted;
-	/*
-	 * If channel is halted due to some error,
-	 * the client should ABORT/FLUSH and START the channel.
-	 */
-	bool faulting;
-	/* Location of last load */
-	u32 src_addr;
-	/* Location of last store */
-	u32 dst_addr;
-	/*
-	 * Pointer to the currently active req, NULL if channel is
-	 * inactive, even though the requests may be present.
-	 */
-	struct pl330_req *top_req;
-	/* Pointer to req waiting second in the queue if any. */
-	struct pl330_req *wait_req;
-};
-
-enum pl330_chan_op {
-	/* Start the channel */
-	PL330_OP_START,
-	/* Abort the active xfer */
-	PL330_OP_ABORT,
-	/* Stop xfer and flush queue */
-	PL330_OP_FLUSH,
-};
-
-extern int pl330_add(struct pl330_info *);
-extern void pl330_del(struct pl330_info *pi);
-extern int pl330_update(const struct pl330_info *pi);
-extern void pl330_release_channel(void *ch_id);
-extern void *pl330_request_channel(const struct pl330_info *pi);
-extern int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus);
-extern int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op);
-extern int pl330_submit_req(void *ch_id, struct pl330_req *r);
+/* Register and Bit field Definitions */
+#define DS		0x0
+#define DS_ST_STOP	0x0
+#define DS_ST_EXEC	0x1
+#define DS_ST_CMISS	0x2
+#define DS_ST_UPDTPC	0x3
+#define DS_ST_WFE	0x4
+#define DS_ST_ATBRR	0x5
+#define DS_ST_QBUSY	0x6
+#define DS_ST_WFP	0x7
+#define DS_ST_KILL	0x8
+#define DS_ST_CMPLT	0x9
+#define DS_ST_FLTCMP	0xe
+#define DS_ST_FAULT	0xf
+
+#define DPC		0x4
+#define INTEN		0x20
+#define ES		0x24
+#define INTSTATUS	0x28
+#define INTCLR		0x2c
+#define FSM		0x30
+#define FSC		0x34
+#define FTM		0x38
+
+#define _FTC		0x40
+#define FTC(n)		(_FTC + (n)*0x4)
+
+#define _CS		0x100
+#define CS(n)		(_CS + (n)*0x8)
+#define CS_CNS		(1 << 21)
+
+#define _CPC		0x104
+#define CPC(n)		(_CPC + (n)*0x8)
+
+#define _SA		0x400
+#define SA(n)		(_SA + (n)*0x20)
+
+#define _DA		0x404
+#define DA(n)		(_DA + (n)*0x20)
+
+#define _CC		0x408
+#define CC(n)		(_CC + (n)*0x20)
+
+#define CC_SRCINC	(1 << 0)
+#define CC_DSTINC	(1 << 14)
+#define CC_SRCPRI	(1 << 8)
+#define CC_DSTPRI	(1 << 22)
+#define CC_SRCNS	(1 << 9)
+#define CC_DSTNS	(1 << 23)
+#define CC_SRCIA	(1 << 10)
+#define CC_DSTIA	(1 << 24)
+#define CC_SRCBRSTLEN_SHFT	4
+#define CC_DSTBRSTLEN_SHFT	18
+#define CC_SRCBRSTSIZE_SHFT	1
+#define CC_DSTBRSTSIZE_SHFT	15
+#define CC_SRCCCTRL_SHFT	11
+#define CC_SRCCCTRL_MASK	0x7
+#define CC_DSTCCTRL_SHFT	25
+#define CC_DRCCCTRL_MASK	0x7
+#define CC_SWAP_SHFT	28
+
+#define _LC0		0x40c
+#define LC0(n)		(_LC0 + (n)*0x20)
+
+#define _LC1		0x410
+#define LC1(n)		(_LC1 + (n)*0x20)
+
+#define DBGSTATUS	0xd00
+#define DBG_BUSY	(1 << 0)
+
+#define DBGCMD		0xd04
+#define DBGINST0	0xd08
+#define DBGINST1	0xd0c
+
+#define CR0		0xe00
+#define CR1		0xe04
+#define CR2		0xe08
+#define CR3		0xe0c
+#define CR4		0xe10
+#define CRD		0xe14
+
+#define PERIPH_ID	0xfe0
+#define PERIPH_REV_SHIFT	20
+#define PERIPH_REV_MASK		0xf
+#define PERIPH_REV_R0P0		0
+#define PERIPH_REV_R1P0		1
+#define PERIPH_REV_R1P1		2
+#define PCELL_ID	0xff0
+
+#define CR0_PERIPH_REQ_SET	(1 << 0)
+#define CR0_BOOT_EN_SET		(1 << 1)
+#define CR0_BOOT_MAN_NS		(1 << 2)
+#define CR0_NUM_CHANS_SHIFT	4
+#define CR0_NUM_CHANS_MASK	0x7
+#define CR0_NUM_PERIPH_SHIFT	12
+#define CR0_NUM_PERIPH_MASK	0x1f
+#define CR0_NUM_EVENTS_SHIFT	17
+#define CR0_NUM_EVENTS_MASK	0x1f
+
+#define CR1_ICACHE_LEN_SHIFT	0
+#define CR1_ICACHE_LEN_MASK	0x7
+#define CR1_NUM_ICACHELINES_SHIFT	4
+#define CR1_NUM_ICACHELINES_MASK	0xf
+
+#define CRD_DATA_WIDTH_SHIFT	0
+#define CRD_DATA_WIDTH_MASK	0x7
+#define CRD_WR_CAP_SHIFT	4
+#define CRD_WR_CAP_MASK		0x7
+#define CRD_WR_Q_DEP_SHIFT	8
+#define CRD_WR_Q_DEP_MASK	0xf
+#define CRD_RD_CAP_SHIFT	12
+#define CRD_RD_CAP_MASK		0x7
+#define CRD_RD_Q_DEP_SHIFT	16
+#define CRD_RD_Q_DEP_MASK	0xf
+#define CRD_DATA_BUFF_SHIFT	20
+#define CRD_DATA_BUFF_MASK	0x3ff
+
+#define	PART		0x330
+#define DESIGNER	0x41
+#define REVISION	0x0
+#define INTEG_CFG	0x0
+#define PERIPH_ID_VAL	((PART << 0) | (DESIGNER << 12))
+
+#define PCELL_ID_VAL	0xb105f00d
+
+#define PL330_STATE_STOPPED		(1 << 0)
+#define PL330_STATE_EXECUTING		(1 << 1)
+#define PL330_STATE_WFE			(1 << 2)
+#define PL330_STATE_FAULTING		(1 << 3)
+#define PL330_STATE_COMPLETING		(1 << 4)
+#define PL330_STATE_WFP			(1 << 5)
+#define PL330_STATE_KILLING		(1 << 6)
+#define PL330_STATE_FAULT_COMPLETING	(1 << 7)
+#define PL330_STATE_CACHEMISS		(1 << 8)
+#define PL330_STATE_UPDTPC		(1 << 9)
+#define PL330_STATE_ATBARRIER		(1 << 10)
+#define PL330_STATE_QUEUEBUSY		(1 << 11)
+#define PL330_STATE_INVALID		(1 << 15)
+
+#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \
+				| PL330_STATE_WFE | PL330_STATE_FAULTING)
+
+#define CMD_DMAADDH	0x54
+#define CMD_DMAEND	0x00
+#define CMD_DMAFLUSHP	0x35
+#define CMD_DMAGO	0xa0
+#define CMD_DMALD	0x04
+#define CMD_DMALDP	0x25
+#define CMD_DMALP	0x20
+#define CMD_DMALPEND	0x28
+#define CMD_DMAKILL	0x01
+#define CMD_DMAMOV	0xbc
+#define CMD_DMANOP	0x18
+#define CMD_DMARMB	0x12
+#define CMD_DMASEV	0x34
+#define CMD_DMAST	0x08
+#define CMD_DMASTP	0x29
+#define CMD_DMASTZ	0x0c
+#define CMD_DMAWFE	0x36
+#define CMD_DMAWFP	0x30
+#define CMD_DMAWMB	0x13
+
+#define SZ_DMAADDH	3
+#define SZ_DMAEND	1
+#define SZ_DMAFLUSHP	2
+#define SZ_DMALD	1
+#define SZ_DMALDP	2
+#define SZ_DMALP	2
+#define SZ_DMALPEND	2
+#define SZ_DMAKILL	1
+#define SZ_DMAMOV	6
+#define SZ_DMANOP	1
+#define SZ_DMARMB	1
+#define SZ_DMASEV	2
+#define SZ_DMAST	1
+#define SZ_DMASTP	2
+#define SZ_DMASTZ	1
+#define SZ_DMAWFE	2
+#define SZ_DMAWFP	2
+#define SZ_DMAWMB	1
+#define SZ_DMAGO	6
+
+#define BRST_LEN(ccr)	((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1)
+#define BRST_SIZE(ccr)	(1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7))
+
+#define BYTE_TO_BURST(b, ccr)  ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr))
+#define BURST_TO_BYTE(c, ccr)  ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr))
 
 #endif	/* __PL330_CORE_H */
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index a4edd19..8c5e828 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -57,7 +57,7 @@ static inline void *kmap_high_get(struct page *page)
 #ifdef CONFIG_HIGHMEM
 extern void *kmap(struct page *page);
 extern void kunmap(struct page *page);
-extern void *__kmap_atomic(struct page *page);
+extern void *kmap_atomic(struct page *page);
 extern void __kunmap_atomic(void *kvaddr);
 extern void *kmap_atomic_pfn(unsigned long pfn);
 extern struct page *kmap_atomic_to_page(const void *ptr);
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index ce280b8..d7038fa 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -55,7 +55,6 @@ struct thread_struct {
 #define start_thread(regs,pc,sp)					\
 ({									\
 	unsigned long *stack = (unsigned long *)sp;			\
-	set_fs(USER_DS);						\
 	memset(regs->uregs, 0, sizeof(regs->uregs));			\
 	if (current->personality & ADDR_LIMIT_32BIT)			\
 		regs->ARM_cpsr = USR_MODE;				\
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 7b46b27..49aa6a9 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -891,7 +891,8 @@ static struct platform_device at91sam9263_isi_device = {
 	.num_resources	= ARRAY_SIZE(isi_resources),
 };
 
-void __init at91_add_device_isi(void)
+void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck)
 {
 	at91_set_A_periph(AT91_PIN_PE0, 0);	/* ISI_D0 */
 	at91_set_A_periph(AT91_PIN_PE1, 0);	/* ISI_D1 */
@@ -904,14 +905,20 @@ void __init at91_add_device_isi(void)
 	at91_set_A_periph(AT91_PIN_PE8, 0);	/* ISI_PCK */
 	at91_set_A_periph(AT91_PIN_PE9, 0);	/* ISI_HSYNC */
 	at91_set_A_periph(AT91_PIN_PE10, 0);	/* ISI_VSYNC */
-	at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */
 	at91_set_B_periph(AT91_PIN_PE12, 0);	/* ISI_PD8 */
 	at91_set_B_periph(AT91_PIN_PE13, 0);	/* ISI_PD9 */
 	at91_set_B_periph(AT91_PIN_PE14, 0);	/* ISI_PD10 */
 	at91_set_B_periph(AT91_PIN_PE15, 0);	/* ISI_PD11 */
+
+	if (use_pck_as_mck) {
+		at91_set_B_periph(AT91_PIN_PE11, 0);	/* ISI_MCK (PCK3) */
+
+		/* TODO: register the PCK for ISI_MCK and set its parent */
+	}
 }
 #else
-void __init at91_add_device_isi(void) {}
+void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck) {}
 #endif
 
 
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index b7582dd..bd4e68c 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -14,6 +14,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/gpio.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
 #include <linux/atmel-mci.h>
@@ -28,7 +29,10 @@
 #include <mach/at_hdmac.h>
 #include <mach/atmel-mci.h>
 
+#include <media/atmel-isi.h>
+
 #include "generic.h"
+#include "clock.h"
 
 
 /* --------------------------------------------------------------------
@@ -38,10 +42,6 @@
 #if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
 static u64 hdmac_dmamask = DMA_BIT_MASK(32);
 
-static struct at_dma_platform_data atdma_pdata = {
-	.nr_channels	= 8,
-};
-
 static struct resource hdmac_resources[] = {
 	[0] = {
 		.start	= AT91SAM9G45_BASE_DMA,
@@ -56,12 +56,11 @@ static struct resource hdmac_resources[] = {
 };
 
 static struct platform_device at_hdmac_device = {
-	.name		= "at_hdmac",
+	.name		= "at91sam9g45_dma",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &hdmac_dmamask,
 				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &atdma_pdata,
 	},
 	.resource	= hdmac_resources,
 	.num_resources	= ARRAY_SIZE(hdmac_resources),
@@ -69,9 +68,15 @@ static struct platform_device at_hdmac_device = {
 
 void __init at91_add_device_hdmac(void)
 {
-	dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask);
-	dma_cap_set(DMA_SLAVE, atdma_pdata.cap_mask);
-	platform_device_register(&at_hdmac_device);
+#if defined(CONFIG_OF)
+	struct device_node *of_node =
+		of_find_node_by_name(NULL, "dma-controller");
+
+	if (of_node)
+		of_node_put(of_node);
+	else
+#endif
+		platform_device_register(&at_hdmac_device);
 }
 #else
 void __init at91_add_device_hdmac(void) {}
@@ -869,6 +874,96 @@ void __init at91_add_device_ac97(struct ac97c_platform_data *data)
 void __init at91_add_device_ac97(struct ac97c_platform_data *data) {}
 #endif
 
+/* --------------------------------------------------------------------
+ *  Image Sensor Interface
+ * -------------------------------------------------------------------- */
+#if defined(CONFIG_VIDEO_ATMEL_ISI) || defined(CONFIG_VIDEO_ATMEL_ISI_MODULE)
+static u64 isi_dmamask = DMA_BIT_MASK(32);
+static struct isi_platform_data isi_data;
+
+struct resource isi_resources[] = {
+	[0] = {
+		.start	= AT91SAM9G45_BASE_ISI,
+		.end	= AT91SAM9G45_BASE_ISI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91SAM9G45_ID_ISI,
+		.end	= AT91SAM9G45_ID_ISI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91sam9g45_isi_device = {
+	.name		= "atmel_isi",
+	.id		= 0,
+	.dev		= {
+			.dma_mask		= &isi_dmamask,
+			.coherent_dma_mask	= DMA_BIT_MASK(32),
+			.platform_data		= &isi_data,
+	},
+	.resource	= isi_resources,
+	.num_resources	= ARRAY_SIZE(isi_resources),
+};
+
+static struct clk_lookup isi_mck_lookups[] = {
+	CLKDEV_CON_DEV_ID("isi_mck", "atmel_isi.0", NULL),
+};
+
+void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck)
+{
+	struct clk *pck;
+	struct clk *parent;
+
+	if (!data)
+		return;
+	isi_data = *data;
+
+	at91_set_A_periph(AT91_PIN_PB20, 0);	/* ISI_D0 */
+	at91_set_A_periph(AT91_PIN_PB21, 0);	/* ISI_D1 */
+	at91_set_A_periph(AT91_PIN_PB22, 0);	/* ISI_D2 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);	/* ISI_D3 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);	/* ISI_D4 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);	/* ISI_D5 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);	/* ISI_D6 */
+	at91_set_A_periph(AT91_PIN_PB27, 0);	/* ISI_D7 */
+	at91_set_A_periph(AT91_PIN_PB28, 0);	/* ISI_PCK */
+	at91_set_A_periph(AT91_PIN_PB30, 0);	/* ISI_HSYNC */
+	at91_set_A_periph(AT91_PIN_PB29, 0);	/* ISI_VSYNC */
+	at91_set_B_periph(AT91_PIN_PB8, 0);	/* ISI_PD8 */
+	at91_set_B_periph(AT91_PIN_PB9, 0);	/* ISI_PD9 */
+	at91_set_B_periph(AT91_PIN_PB10, 0);	/* ISI_PD10 */
+	at91_set_B_periph(AT91_PIN_PB11, 0);	/* ISI_PD11 */
+
+	platform_device_register(&at91sam9g45_isi_device);
+
+	if (use_pck_as_mck) {
+		at91_set_B_periph(AT91_PIN_PB31, 0);	/* ISI_MCK (PCK1) */
+
+		pck = clk_get(NULL, "pck1");
+		parent = clk_get(NULL, "plla");
+
+		BUG_ON(IS_ERR(pck) || IS_ERR(parent));
+
+		if (clk_set_parent(pck, parent)) {
+			pr_err("Failed to set PCK's parent\n");
+		} else {
+			/* Register PCK as ISI_MCK */
+			isi_mck_lookups[0].clk = pck;
+			clkdev_add_table(isi_mck_lookups,
+					ARRAY_SIZE(isi_mck_lookups));
+		}
+
+		clk_put(pck);
+		clk_put(parent);
+	}
+}
+#else
+void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck) {}
+#endif
+
 
 /* --------------------------------------------------------------------
  *  LCD Controller
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 61908dc..9be71c1 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -33,10 +33,6 @@
 #if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
 static u64 hdmac_dmamask = DMA_BIT_MASK(32);
 
-static struct at_dma_platform_data atdma_pdata = {
-	.nr_channels	= 2,
-};
-
 static struct resource hdmac_resources[] = {
 	[0] = {
 		.start	= AT91SAM9RL_BASE_DMA,
@@ -51,12 +47,11 @@ static struct resource hdmac_resources[] = {
 };
 
 static struct platform_device at_hdmac_device = {
-	.name		= "at_hdmac",
+	.name		= "at91sam9rl_dma",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &hdmac_dmamask,
 				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &atdma_pdata,
 	},
 	.resource	= hdmac_resources,
 	.num_resources	= ARRAY_SIZE(hdmac_resources),
@@ -64,7 +59,6 @@ static struct platform_device at_hdmac_device = {
 
 void __init at91_add_device_hdmac(void)
 {
-	dma_cap_set(DMA_MEMCPY, atdma_pdata.cap_mask);
 	platform_device_register(&at_hdmac_device);
 }
 #else
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index ea0d1b9..57497e2 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -24,11 +24,13 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/leds.h>
-#include <linux/clk.h>
 #include <linux/atmel-mci.h>
+#include <linux/delay.h>
 
 #include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
+#include <media/soc_camera.h>
+#include <media/atmel-isi.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -185,6 +187,71 @@ static void __init ek_add_device_nand(void)
 
 
 /*
+ *  ISI
+ */
+static struct isi_platform_data __initdata isi_data = {
+	.frate			= ISI_CFG1_FRATE_CAPTURE_ALL,
+	/* to use codec and preview path simultaneously */
+	.full_mode		= 1,
+	.data_width_flags	= ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10,
+	/* ISI_MCK is provided by programmable clock or external clock */
+	.mck_hz			= 25000000,
+};
+
+
+/*
+ * soc-camera OV2640
+ */
+#if defined(CONFIG_SOC_CAMERA_OV2640) || \
+	defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
+static unsigned long isi_camera_query_bus_param(struct soc_camera_link *link)
+{
+	/* ISI board for ek using default 8-bits connection */
+	return SOCAM_DATAWIDTH_8;
+}
+
+static int i2c_camera_power(struct device *dev, int on)
+{
+	/* enable or disable the camera */
+	pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
+	at91_set_gpio_output(AT91_PIN_PD13, !on);
+
+	if (!on)
+		goto out;
+
+	/* If enabled, give a reset impulse */
+	at91_set_gpio_output(AT91_PIN_PD12, 0);
+	msleep(20);
+	at91_set_gpio_output(AT91_PIN_PD12, 1);
+	msleep(100);
+
+out:
+	return 0;
+}
+
+static struct i2c_board_info i2c_camera = {
+	I2C_BOARD_INFO("ov2640", 0x30),
+};
+
+static struct soc_camera_link iclink_ov2640 = {
+	.bus_id			= 0,
+	.board_info		= &i2c_camera,
+	.i2c_adapter_id		= 0,
+	.power			= i2c_camera_power,
+	.query_bus_param	= isi_camera_query_bus_param,
+};
+
+static struct platform_device isi_ov2640 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_ov2640,
+	},
+};
+#endif
+
+
+/*
  * LCD Controller
  */
 #if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
@@ -377,7 +444,12 @@ static struct gpio_led ek_pwm_led[] = {
 #endif
 };
 
-
+static struct platform_device *devices[] __initdata = {
+#if defined(CONFIG_SOC_CAMERA_OV2640) || \
+	defined(CONFIG_SOC_CAMERA_OV2640_MODULE)
+	&isi_ov2640,
+#endif
+};
 
 static void __init ek_board_init(void)
 {
@@ -399,6 +471,8 @@ static void __init ek_board_init(void)
 	ek_add_device_nand();
 	/* I2C */
 	at91_add_device_i2c(0, NULL, 0);
+	/* ISI, using programmable clock as ISI_MCK */
+	at91_add_device_isi(&isi_data, true);
 	/* LCD Controller */
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* Touch Screen */
@@ -410,6 +484,8 @@ static void __init ek_board_init(void)
 	/* LEDs */
 	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 	at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
+	/* Other platform devices */
+	platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index d0b377b..281f6de 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -107,6 +107,8 @@ struct atmel_nand_data {
 	u8		ale;		/* address line number connected to ALE */
 	u8		cle;		/* address line number connected to CLE */
 	u8		bus_width_16;	/* buswidth is 16 bit */
+	u8		correction_cap; /* PMECC correction capability */
+	u16		sector_size;    /* Sector size for PMECC */
 	struct mtd_partition *parts;
 	unsigned int	num_parts;
 };
@@ -179,7 +181,9 @@ extern void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data);
 extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
 
  /* ISI */
-extern void __init at91_add_device_isi(void);
+struct isi_platform_data;
+extern void __init at91_add_device_isi(struct isi_platform_data *data,
+		bool use_pck_as_mck);
 
  /* Touchscreen Controller */
 struct at91_tsadcc_data {
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 5d602f6..bd4600e 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -230,6 +230,7 @@ config MACH_UNIVERSAL_C210
 	select S5P_DEV_FIMC1
 	select S5P_DEV_FIMC2
 	select S5P_DEV_FIMC3
+	select S5P_DEV_G2D
 	select S5P_DEV_CSIS0
 	select S5P_DEV_FIMD0
 	select S3C_DEV_HSMMC
@@ -273,6 +274,7 @@ config MACH_NURI
 	select S5P_DEV_FIMC1
 	select S5P_DEV_FIMC2
 	select S5P_DEV_FIMC3
+	select S5P_DEV_G2D
 	select S5P_DEV_MFC
 	select S5P_DEV_USB_EHCI
 	select S5P_SETUP_MIPIPHY
@@ -303,6 +305,7 @@ config MACH_ORIGEN
 	select S5P_DEV_FIMC2
 	select S5P_DEV_FIMC3
 	select S5P_DEV_FIMD0
+	select S5P_DEV_G2D
 	select S5P_DEV_I2C_HDMIPHY
 	select S5P_DEV_MFC
 	select S5P_DEV_TV
diff --git a/arch/arm/mach-exynos/clock.c b/arch/arm/mach-exynos/clock.c
index 5a8c42e..268b356 100644
--- a/arch/arm/mach-exynos/clock.c
+++ b/arch/arm/mach-exynos/clock.c
@@ -783,6 +783,13 @@ static struct clk clk_pdma1 = {
 	.ctrlbit	= (1 << 1),
 };
 
+static struct clk clk_mdma1 = {
+	.name		= "dma",
+	.devname	= "dma-pl330.2",
+	.enable		= exynos4_clk_ip_image_ctrl,
+	.ctrlbit	= ((1 << 8) | (1 << 5) | (1 << 2)),
+};
+
 struct clk *clkset_group_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = &clk_xusbxti,
@@ -1301,6 +1308,7 @@ static struct clksrc_clk *sysclks[] = {
 static struct clk *clk_cdev[] = {
 	&clk_pdma0,
 	&clk_pdma1,
+	&clk_mdma1,
 };
 
 static struct clksrc_clk *clksrc_cdev[] = {
@@ -1329,6 +1337,7 @@ static struct clk_lookup exynos4_clk_lookup[] = {
 	CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
 	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0),
 	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1),
+	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &clk_mdma1),
 	CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &clk_sclk_spi0.clk),
 	CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &clk_sclk_spi1.clk),
 	CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &clk_sclk_spi2.clk),
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index c59e188..ab9c8ea 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -173,7 +173,12 @@ static struct map_desc exynos4_iodesc[] __initdata = {
 	}, {
 		.virtual	= (unsigned long)S5P_VA_DMC0,
 		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC0),
-		.length		= SZ_4K,
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC1,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC1),
+		.length		= SZ_64K,
 		.type		= MT_DEVICE,
 	}, {
 		.virtual	= (unsigned long)S3C_VA_USB_HSPHY,
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index b10fcd2..ce645ba 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -29,6 +29,7 @@
 #include <asm/irq.h>
 #include <plat/devs.h>
 #include <plat/irqs.h>
+#include <plat/cpu.h>
 
 #include <mach/map.h>
 #include <mach/irqs.h>
@@ -36,7 +37,7 @@
 
 static u64 dma_dmamask = DMA_BIT_MASK(32);
 
-u8 pdma0_peri[] = {
+u8 exynos4210_pdma0_peri[] = {
 	DMACH_PCM0_RX,
 	DMACH_PCM0_TX,
 	DMACH_PCM2_RX,
@@ -69,11 +70,43 @@ u8 pdma0_peri[] = {
 	DMACH_AC97_PCMOUT,
 };
 
-struct dma_pl330_platdata exynos4_pdma0_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
-	.peri_id = pdma0_peri,
+u8 exynos4212_pdma0_peri[] = {
+	DMACH_PCM0_RX,
+	DMACH_PCM0_TX,
+	DMACH_PCM2_RX,
+	DMACH_PCM2_TX,
+	DMACH_MIPI_HSI0,
+	DMACH_MIPI_HSI1,
+	DMACH_SPI0_RX,
+	DMACH_SPI0_TX,
+	DMACH_SPI2_RX,
+	DMACH_SPI2_TX,
+	DMACH_I2S0S_TX,
+	DMACH_I2S0_RX,
+	DMACH_I2S0_TX,
+	DMACH_I2S2_RX,
+	DMACH_I2S2_TX,
+	DMACH_UART0_RX,
+	DMACH_UART0_TX,
+	DMACH_UART2_RX,
+	DMACH_UART2_TX,
+	DMACH_UART4_RX,
+	DMACH_UART4_TX,
+	DMACH_SLIMBUS0_RX,
+	DMACH_SLIMBUS0_TX,
+	DMACH_SLIMBUS2_RX,
+	DMACH_SLIMBUS2_TX,
+	DMACH_SLIMBUS4_RX,
+	DMACH_SLIMBUS4_TX,
+	DMACH_AC97_MICIN,
+	DMACH_AC97_PCMIN,
+	DMACH_AC97_PCMOUT,
+	DMACH_MIPI_HSI4,
+	DMACH_MIPI_HSI5,
 };
 
+struct dma_pl330_platdata exynos4_pdma0_pdata;
+
 struct amba_device exynos4_device_pdma0 = {
 	.dev = {
 		.init_name = "dma-pl330.0",
@@ -90,7 +123,7 @@ struct amba_device exynos4_device_pdma0 = {
 	.periphid = 0x00041330,
 };
 
-u8 pdma1_peri[] = {
+u8 exynos4210_pdma1_peri[] = {
 	DMACH_PCM0_RX,
 	DMACH_PCM0_TX,
 	DMACH_PCM1_RX,
@@ -118,11 +151,41 @@ u8 pdma1_peri[] = {
 	DMACH_SLIMBUS5_TX,
 };
 
-struct dma_pl330_platdata exynos4_pdma1_pdata = {
-	.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
-	.peri_id = pdma1_peri,
+u8 exynos4212_pdma1_peri[] = {
+	DMACH_PCM0_RX,
+	DMACH_PCM0_TX,
+	DMACH_PCM1_RX,
+	DMACH_PCM1_TX,
+	DMACH_MIPI_HSI2,
+	DMACH_MIPI_HSI3,
+	DMACH_SPI1_RX,
+	DMACH_SPI1_TX,
+	DMACH_I2S0S_TX,
+	DMACH_I2S0_RX,
+	DMACH_I2S0_TX,
+	DMACH_I2S1_RX,
+	DMACH_I2S1_TX,
+	DMACH_UART0_RX,
+	DMACH_UART0_TX,
+	DMACH_UART1_RX,
+	DMACH_UART1_TX,
+	DMACH_UART3_RX,
+	DMACH_UART3_TX,
+	DMACH_SLIMBUS1_RX,
+	DMACH_SLIMBUS1_TX,
+	DMACH_SLIMBUS3_RX,
+	DMACH_SLIMBUS3_TX,
+	DMACH_SLIMBUS5_RX,
+	DMACH_SLIMBUS5_TX,
+	DMACH_SLIMBUS0AUX_RX,
+	DMACH_SLIMBUS0AUX_TX,
+	DMACH_SPDIF,
+	DMACH_MIPI_HSI6,
+	DMACH_MIPI_HSI7,
 };
 
+struct dma_pl330_platdata exynos4_pdma1_pdata;
+
 struct amba_device exynos4_device_pdma1 = {
 	.dev = {
 		.init_name = "dma-pl330.1",
@@ -139,11 +202,59 @@ struct amba_device exynos4_device_pdma1 = {
 	.periphid = 0x00041330,
 };
 
+u8 mdma_peri[] = {
+	DMACH_MTOM_0,
+	DMACH_MTOM_1,
+	DMACH_MTOM_2,
+	DMACH_MTOM_3,
+	DMACH_MTOM_4,
+	DMACH_MTOM_5,
+	DMACH_MTOM_6,
+	DMACH_MTOM_7,
+};
+
+struct dma_pl330_platdata exynos4_mdma_pdata = {
+	.nr_valid_peri = ARRAY_SIZE(mdma_peri),
+	.peri_id = mdma_peri,
+};
+
+struct amba_device exynos4_device_mdma = {
+	.dev = {
+		.init_name = "dma-pl330.2",
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_mdma_pdata,
+	},
+	.res = {
+		.start = EXYNOS4_PA_MDMA1,
+		.end = EXYNOS4_PA_MDMA1 + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_MDMA1, NO_IRQ},
+	.periphid = 0x00041330,
+};
+
 static int __init exynos4_dma_init(void)
 {
 	if (of_have_populated_dt())
 		return 0;
 
+	if (soc_is_exynos4210()) {
+		exynos4_pdma0_pdata.nr_valid_peri =
+			ARRAY_SIZE(exynos4210_pdma0_peri);
+		exynos4_pdma0_pdata.peri_id = exynos4210_pdma0_peri;
+		exynos4_pdma1_pdata.nr_valid_peri =
+			ARRAY_SIZE(exynos4210_pdma1_peri);
+		exynos4_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+	} else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+		exynos4_pdma0_pdata.nr_valid_peri =
+			ARRAY_SIZE(exynos4212_pdma0_peri);
+		exynos4_pdma0_pdata.peri_id = exynos4212_pdma0_peri;
+		exynos4_pdma1_pdata.nr_valid_peri =
+			ARRAY_SIZE(exynos4212_pdma1_peri);
+		exynos4_pdma1_pdata.peri_id = exynos4212_pdma1_peri;
+	}
+
 	dma_cap_set(DMA_SLAVE, exynos4_pdma0_pdata.cap_mask);
 	dma_cap_set(DMA_CYCLIC, exynos4_pdma0_pdata.cap_mask);
 	amba_device_register(&exynos4_device_pdma0, &iomem_resource);
@@ -152,6 +263,9 @@ static int __init exynos4_dma_init(void)
 	dma_cap_set(DMA_CYCLIC, exynos4_pdma1_pdata.cap_mask);
 	amba_device_register(&exynos4_device_pdma1, &iomem_resource);
 
+	dma_cap_set(DMA_MEMCPY, exynos4_mdma_pdata.cap_mask);
+	amba_device_register(&exynos4_device_mdma, &iomem_resource);
+
 	return 0;
 }
 arch_initcall(exynos4_dma_init);
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index f77bce0..1d401c9 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -43,6 +43,8 @@
 #define IRQ_EINT15		IRQ_SPI(31)
 #define IRQ_EINT16_31		IRQ_SPI(32)
 
+#define IRQ_MDMA0		IRQ_SPI(33)
+#define IRQ_MDMA1		IRQ_SPI(34)
 #define IRQ_PDMA0		IRQ_SPI(35)
 #define IRQ_PDMA1		IRQ_SPI(36)
 #define IRQ_TIMER0_VIC		IRQ_SPI(37)
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index c754a22..c15ed14 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -31,6 +31,8 @@
 #define EXYNOS4_PA_FIMC2		0x11820000
 #define EXYNOS4_PA_FIMC3		0x11830000
 
+#define EXYNOS4_PA_G2D			0x12800000
+
 #define EXYNOS4_PA_I2S0			0x03830000
 #define EXYNOS4_PA_I2S1			0xE3100000
 #define EXYNOS4_PA_I2S2			0xE2A00000
@@ -57,6 +59,7 @@
 #define EXYNOS4_PA_KEYPAD		0x100A0000
 
 #define EXYNOS4_PA_DMC0			0x10400000
+#define EXYNOS4_PA_DMC1			0x10410000
 
 #define EXYNOS4_PA_COMBINER		0x10440000
 
@@ -67,7 +70,8 @@
 #define EXYNOS4_PA_TWD			0x10500600
 #define EXYNOS4_PA_L2CC			0x10502000
 
-#define EXYNOS4_PA_MDMA			0x10810000
+#define EXYNOS4_PA_MDMA0		0x10810000
+#define EXYNOS4_PA_MDMA1		0x12840000
 #define EXYNOS4_PA_PDMA0		0x12680000
 #define EXYNOS4_PA_PDMA1		0x12690000
 
@@ -162,6 +166,7 @@
 #define S5P_PA_FIMC1			EXYNOS4_PA_FIMC1
 #define S5P_PA_FIMC2			EXYNOS4_PA_FIMC2
 #define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
+#define S5P_PA_G2D			EXYNOS4_PA_G2D
 #define S5P_PA_FIMD0			EXYNOS4_PA_FIMD0
 #define S5P_PA_HDMI			EXYNOS4_PA_HDMI
 #define S5P_PA_IIC_HDMIPHY		EXYNOS4_PA_IIC_HDMIPHY
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h
index 6c37ebe..2003251 100644
--- a/arch/arm/mach-exynos/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
@@ -77,6 +77,7 @@
 #define S5P_CLKDIV2_RATIO		S5P_CLKREG(0x0C580)
 
 #define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
+#define S5P_CLKDIV_STAT_MFC		S5P_CLKREG(0x0C628)
 
 #define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
 #define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
@@ -104,8 +105,12 @@
 #define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
 #define S5P_CLKDIV_DMC1			S5P_CLKREG(0x10504)
 #define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
+#define S5P_CLKDIV_STAT_DMC1		S5P_CLKREG(0x10604)
 #define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
 
+#define S5P_DMC_PAUSE_CTRL		S5P_CLKREG(0x11094)
+#define DMC_PAUSE_ENABLE		(1 << 0)
+
 #define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
 #define S5P_MPLL_LOCK			(soc_is_exynos4210() ? \
 					S5P_CLKREG(0x14004) :  \
@@ -178,6 +183,22 @@
 #define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
 #define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
 
+#define S5P_CLKDIV_DMC1_G2D_ACP_SHIFT	(0)
+#define S5P_CLKDIV_DMC1_G2D_ACP_MASK	(0xf << S5P_CLKDIV_DMC1_G2D_ACP_SHIFT)
+#define S5P_CLKDIV_DMC1_C2C_SHIFT	(4)
+#define S5P_CLKDIV_DMC1_C2C_MASK	(0x7 << S5P_CLKDIV_DMC1_C2C_SHIFT)
+#define S5P_CLKDIV_DMC1_PWI_SHIFT	(8)
+#define S5P_CLKDIV_DMC1_PWI_MASK	(0xf << S5P_CLKDIV_DMC1_PWI_SHIFT)
+#define S5P_CLKDIV_DMC1_C2CACLK_SHIFT	(12)
+#define S5P_CLKDIV_DMC1_C2CACLK_MASK	(0x7 << S5P_CLKDIV_DMC1_C2CACLK_SHIFT)
+#define S5P_CLKDIV_DMC1_DVSEM_SHIFT	(16)
+#define S5P_CLKDIV_DMC1_DVSEM_MASK	(0x7f << S5P_CLKDIV_DMC1_DVSEM_SHIFT)
+#define S5P_CLKDIV_DMC1_DPM_SHIFT	(24)
+#define S5P_CLKDIV_DMC1_DPM_MASK	(0x7f << S5P_CLKDIV_DMC1_DPM_SHIFT)
+
+#define S5P_CLKDIV_MFC_SHIFT		(0)
+#define S5P_CLKDIV_MFC_MASK		(0x7 << S5P_CLKDIV_MFC_SHIFT)
+
 #define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
 #define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
 #define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
@@ -188,12 +209,25 @@
 #define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
 #define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
 #define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK266_GPS_SHIFT	(20)
+#define S5P_CLKDIV_TOP_ACLK266_GPS_MASK		(0x7 << S5P_CLKDIV_TOP_ACLK266_GPS_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK400_MCUISP_SHIFT	(24)
+#define S5P_CLKDIV_TOP_ACLK400_MCUISP_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK400_MCUISP_SHIFT)
 
 #define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
 #define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
 #define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
 #define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
 
+#define S5P_CLKDIV_CAM_FIMC0_SHIFT	(0)
+#define S5P_CLKDIV_CAM_FIMC0_MASK	(0xf << S5P_CLKDIV_CAM_FIMC0_SHIFT)
+#define S5P_CLKDIV_CAM_FIMC1_SHIFT	(4)
+#define S5P_CLKDIV_CAM_FIMC1_MASK	(0xf << S5P_CLKDIV_CAM_FIMC1_SHIFT)
+#define S5P_CLKDIV_CAM_FIMC2_SHIFT	(8)
+#define S5P_CLKDIV_CAM_FIMC2_MASK	(0xf << S5P_CLKDIV_CAM_FIMC2_SHIFT)
+#define S5P_CLKDIV_CAM_FIMC3_SHIFT	(12)
+#define S5P_CLKDIV_CAM_FIMC3_MASK	(0xf << S5P_CLKDIV_CAM_FIMC3_SHIFT)
+
 /* Only for EXYNOS4210 */
 
 #define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
@@ -201,6 +235,14 @@
 #define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
 #define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
 
+/* Only for EXYNOS4212 */
+#define S5P_CLKDIV_CAM1			S5P_CLKREG(0x0C568)
+
+#define S5P_CLKDIV_STAT_CAM1		S5P_CLKREG(0x0C668)
+
+#define S5P_CLKDIV_CAM1_JPEG_SHIFT	(0)
+#define S5P_CLKDIV_CAM1_JPEG_MASK	(0xf << S5P_CLKDIV_CAM1_JPEG_SHIFT)
+
 /* Compatibility defines and inclusion */
 
 #include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index b895ec0..40b4b4f 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -431,7 +431,7 @@ static struct regulator_consumer_supply __initdata max8997_buck1_[] = {
 	REGULATOR_SUPPLY("vdd_arm", NULL), /* CPUFREQ */
 };
 static struct regulator_consumer_supply __initdata max8997_buck2_[] = {
-	REGULATOR_SUPPLY("vdd_int", NULL), /* CPUFREQ */
+	REGULATOR_SUPPLY("vdd_int", "exynos4210-busfreq.0"), /* CPUFREQ */
 };
 static struct regulator_consumer_supply __initdata max8997_buck3_[] = {
 	REGULATOR_SUPPLY("vdd", "mali_dev.0"), /* G3D of Exynos 4 */
@@ -742,7 +742,7 @@ static struct regulator_init_data __initdata max8997_buck2_data = {
 	.constraints	= {
 		.name		= "VINT_1.1V_C210",
 		.min_uV		= 900000,
-		.max_uV		= 1100000,
+		.max_uV		= 1200000,
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
 		.always_on	= 1,
 		.state_mem	= {
@@ -957,7 +957,6 @@ static struct max8997_platform_data __initdata nuri_max8997_pdata = {
 	.regulators		= nuri_max8997_regulators,
 
 	.buck125_gpios = { EXYNOS4_GPX0(5), EXYNOS4_GPX0(6), EXYNOS4_GPL0(0) },
-	.buck2_gpiodvs = true,
 
 	.buck1_voltage[0] = 1350000, /* 1.35V */
 	.buck1_voltage[1] = 1300000, /* 1.3V */
@@ -1239,6 +1238,11 @@ static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
 	.sda_delay	= 200,
 };
 
+/* DEVFREQ controlling memory/bus */
+static struct platform_device exynos4_bus_devfreq = {
+	.name			= "exynos4210-busfreq",
+};
+
 static struct platform_device *nuri_devices[] __initdata = {
 	/* Samsung Platform Devices */
 	&s3c_device_i2c5, /* PMIC should initialize first */
@@ -1259,6 +1263,7 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&s3c_device_i2c3,
 	&i2c9_gpio,
 	&s3c_device_adc,
+	&s5p_device_g2d,
 	&s3c_device_rtc,
 	&s5p_device_mfc,
 	&s5p_device_mfc_l,
@@ -1276,6 +1281,7 @@ static struct platform_device *nuri_devices[] __initdata = {
 	&nuri_max8903_device,
 	&cam_vdda_fixed_rdev,
 	&cam_8m_12v_fixed_rdev,
+	&exynos4_bus_devfreq,
 };
 
 static void __init nuri_map_io(void)
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 0679b8a..e1d87b9 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -20,6 +20,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8997.h>
 #include <linux/lcd.h>
+#include <linux/rfkill-gpio.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -235,6 +236,7 @@ static struct regulator_init_data __initdata max8997_ldo9_data = {
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
+		.always_on	= 1,
 		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 		.state_mem	= {
 			.disabled	= 1,
@@ -278,6 +280,7 @@ static struct regulator_init_data __initdata max8997_ldo14_data = {
 		.min_uV		= 1800000,
 		.max_uV		= 1800000,
 		.apply_uV	= 1,
+		.always_on	= 1,
 		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 		.state_mem	= {
 			.disabled	= 1,
@@ -293,6 +296,7 @@ static struct regulator_init_data __initdata max8997_ldo17_data = {
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
+		.always_on	= 1,
 		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 		.state_mem	= {
 			.disabled	= 1,
@@ -602,6 +606,23 @@ static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
 	.setup_gpio	= exynos4_fimd0_gpio_setup_24bpp,
 };
 
+/* Bluetooth rfkill gpio platform data */
+struct rfkill_gpio_platform_data origen_bt_pdata = {
+	.reset_gpio	= EXYNOS4_GPX2(2),
+	.shutdown_gpio	= -1,
+	.type		= RFKILL_TYPE_BLUETOOTH,
+	.name		= "origen-bt",
+};
+
+/* Bluetooth Platform device */
+static struct platform_device origen_device_bluetooth = {
+	.name		= "rfkill_gpio",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &origen_bt_pdata,
+	},
+};
+
 static struct platform_device *origen_devices[] __initdata = {
 	&s3c_device_hsmmc2,
 	&s3c_device_hsmmc0,
@@ -614,6 +635,7 @@ static struct platform_device *origen_devices[] __initdata = {
 	&s5p_device_fimc2,
 	&s5p_device_fimc3,
 	&s5p_device_fimd0,
+	&s5p_device_g2d,
 	&s5p_device_hdmi,
 	&s5p_device_i2c_hdmiphy,
 	&s5p_device_mfc,
@@ -630,6 +652,7 @@ static struct platform_device *origen_devices[] __initdata = {
 	&exynos4_device_pd[PD_MFC],
 	&origen_device_gpiokeys,
 	&origen_lcd_hv070wsa,
+	&origen_device_bluetooth,
 };
 
 /* LCD Backlight data */
@@ -643,6 +666,16 @@ static struct platform_pwm_backlight_data origen_bl_data = {
 	.pwm_period_ns	= 1000,
 };
 
+static void __init origen_bt_setup(void)
+{
+	gpio_request(EXYNOS4_GPA0(0), "GPIO BT_UART");
+	/* 4 UART Pins configuration */
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPA0(0), 4, S3C_GPIO_SFN(2));
+	/* Setup BT Reset, this gpio will be requesed by rfkill-gpio */
+	s3c_gpio_cfgpin(EXYNOS4_GPX2(2), S3C_GPIO_OUTPUT);
+	s3c_gpio_setpull(EXYNOS4_GPX2(2), S3C_GPIO_PULL_NONE);
+}
+
 static void s5p_tv_setup(void)
 {
 	/* Direct HPD to HDMI chip */
@@ -703,6 +736,8 @@ static void __init origen_machine_init(void)
 	s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
 
 	samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
+
+	origen_bt_setup();
 }
 
 MACHINE_START(ORIGEN, "ORIGEN")
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 37ac93e..dd75101 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -960,6 +960,7 @@ static struct platform_device *universal_devices[] __initdata = {
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
 	&s5p_device_fimc3,
+	&s5p_device_g2d,
 	&mmc0_fixed_voltage,
 	&s3c_device_hsmmc0,
 	&s3c_device_hsmmc2,
diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/include/mach/system.h
index 4d9c1f8..5e68cd4 100644
--- a/arch/arm/mach-gemini/include/mach/system.h
+++ b/arch/arm/mach-gemini/include/mach/system.h
@@ -28,6 +28,7 @@ static inline void arch_idle(void)
 	cpu_do_idle();
 }
 
+#error Fix me up
 static inline void arch_reset(char mode, const char *cmd)
 {
 	__raw_writel(RESET_GLOBAL | RESET_CPU1,
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 0e6de36..09f357b 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -22,6 +22,18 @@ config ARCH_MX25
 config MACH_MX27
 	bool
 
+config ARCH_MX5
+	bool
+
+config ARCH_MX50
+	bool
+
+config ARCH_MX51
+	bool
+
+config ARCH_MX53
+	bool
+
 config SOC_IMX1
 	bool
 	select ARCH_MX1
@@ -73,6 +85,32 @@ config SOC_IMX35
 	select MXC_AVIC
 	select SMP_ON_UP if SMP
 
+config SOC_IMX5
+	select CPU_V7
+	select ARM_L1_CACHE_SHIFT_6
+	select MXC_TZIC
+	select ARCH_MXC_IOMUX_V3
+	select ARCH_MXC_AUDMUX_V2
+	select ARCH_HAS_CPUFREQ
+	select ARCH_MX5
+	bool
+
+config SOC_IMX50
+	bool
+	select SOC_IMX5
+	select ARCH_MX50
+
+config	SOC_IMX51
+	bool
+	select SOC_IMX5
+	select ARCH_MX5
+	select ARCH_MX51
+
+config	SOC_IMX53
+	bool
+	select SOC_IMX5
+	select ARCH_MX5
+	select ARCH_MX53
 
 if ARCH_IMX_V4_V5
 
@@ -592,6 +630,207 @@ config MACH_VPR200
 	  Include support for VPR200 platform. This includes specific
 	  configurations for the board and its peripherals.
 
+comment "i.MX5 platforms:"
+
+config MACH_MX50_RDP
+	bool "Support MX50 reference design platform"
+	depends on BROKEN
+	select SOC_IMX50
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for MX50 reference design platform (RDP) board. This
+	  includes specific configurations for the board and its peripherals.
+
+comment "i.MX51 machines:"
+
+config MACH_IMX51_DT
+	bool "Support i.MX51 platforms from device tree"
+	select SOC_IMX51
+	select USE_OF
+	select MACH_MX51_BABBAGE
+	help
+	  Include support for Freescale i.MX51 based platforms
+	  using the device tree for discovery
+
+config MACH_MX51_BABBAGE
+	bool "Support MX51 BABBAGE platforms"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for MX51 Babbage platform, also known as MX51EVK in
+	  u-boot. This includes specific configurations for the board and its
+	  peripherals.
+
+config MACH_MX51_3DS
+	bool "Support MX51PDK (3DS)"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_DEBUG_BOARD
+	help
+	  Include support for MX51PDK (3DS) platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_EUKREA_CPUIMX51
+	bool "Support Eukrea CPUIMX51 module"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for Eukrea CPUIMX51 platform. This includes
+	  specific configurations for the module and its peripherals.
+
+choice
+	prompt "Baseboard"
+	depends on MACH_EUKREA_CPUIMX51
+	default MACH_EUKREA_MBIMX51_BASEBOARD
+
+config MACH_EUKREA_MBIMX51_BASEBOARD
+	prompt "Eukrea MBIMX51 development board"
+	bool
+	select IMX_HAVE_PLATFORM_IMX_KEYPAD
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select LEDS_GPIO_REGISTER
+	help
+	  This adds board specific devices that can be found on Eukrea's
+	  MBIMX51 evaluation board.
+
+endchoice
+
+config MACH_EUKREA_CPUIMX51SD
+	bool "Support Eukrea CPUIMX51SD module"
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	help
+	  Include support for Eukrea CPUIMX51SD platform. This includes
+	  specific configurations for the module and its peripherals.
+
+choice
+	prompt "Baseboard"
+	depends on MACH_EUKREA_CPUIMX51SD
+	default MACH_EUKREA_MBIMXSD51_BASEBOARD
+
+config MACH_EUKREA_MBIMXSD51_BASEBOARD
+	prompt "Eukrea MBIMXSD development board"
+	bool
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select LEDS_GPIO_REGISTER
+	help
+	  This adds board specific devices that can be found on Eukrea's
+	  MBIMXSD evaluation board.
+
+endchoice
+
+config MX51_EFIKA_COMMON
+	bool
+	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_PATA_IMX
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_ULPI if USB_ULPI
+
+config MACH_MX51_EFIKAMX
+	bool "Support MX51 Genesi Efika MX nettop"
+	select LEDS_GPIO_REGISTER
+	select MX51_EFIKA_COMMON
+	help
+	  Include support for Genesi Efika MX nettop. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX51_EFIKASB
+	bool "Support MX51 Genesi Efika Smartbook"
+	select LEDS_GPIO_REGISTER
+	select MX51_EFIKA_COMMON
+	help
+	  Include support for Genesi Efika Smartbook. This includes specific
+	  configurations for the board and its peripherals.
+
+comment "i.MX53 machines:"
+
+config MACH_IMX53_DT
+	bool "Support i.MX53 platforms from device tree"
+	select SOC_IMX53
+	select USE_OF
+	select MACH_MX53_ARD
+	select MACH_MX53_EVK
+	select MACH_MX53_LOCO
+	select MACH_MX53_SMD
+	help
+	  Include support for Freescale i.MX53 based platforms
+	  using the device tree for discovery
+
+config MACH_MX53_EVK
+	bool "Support MX53 EVK platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_SPI_IMX
+	select LEDS_GPIO_REGISTER
+	help
+	  Include support for MX53 EVK platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX53_SMD
+	bool "Support MX53 SMD platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	help
+	  Include support for MX53 SMD platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX53_LOCO
+	bool "Support MX53 LOCO platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_GPIO_KEYS
+	select LEDS_GPIO_REGISTER
+	help
+	  Include support for MX53 LOCO platform. This includes specific
+	  configurations for the board and its peripherals.
+
+config MACH_MX53_ARD
+	bool "Support MX53 ARD platforms"
+	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_GPIO_KEYS
+	help
+	  Include support for MX53 ARD platform. This includes specific
+	  configurations for the board and its peripherals.
+
 comment "i.MX6 family:"
 
 config SOC_IMX6Q
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index f5920c2..88531b6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
 
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clock-mx51-mx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
 
@@ -70,6 +72,26 @@ AFLAGS_head-v7.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SMP) += platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+
+# i.MX5 based machines
+obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
+obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o
+obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o
+obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o
+obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o
+obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += mach-cpuimx51.o
+obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
+obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
+obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
+obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o
+obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
+
+obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
+obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
+
 obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
 
 ifeq ($(CONFIG_PM),y)
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index 5f4d06a..6dfdbcc 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -22,6 +22,18 @@ zreladdr-$(CONFIG_SOC_IMX35)	+= 0x80008000
 params_phys-$(CONFIG_SOC_IMX35)	:= 0x80000100
 initrd_phys-$(CONFIG_SOC_IMX35)	:= 0x80800000
 
+zreladdr-$(CONFIG_SOC_IMX50)	+= 0x70008000
+params_phys-$(CONFIG_SOC_IMX50)	:= 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX50)	:= 0x70800000
+
+zreladdr-$(CONFIG_SOC_IMX51)	+= 0x90008000
+params_phys-$(CONFIG_SOC_IMX51)	:= 0x90000100
+initrd_phys-$(CONFIG_SOC_IMX51)	:= 0x90800000
+
+zreladdr-$(CONFIG_SOC_IMX53)	+= 0x70008000
+params_phys-$(CONFIG_SOC_IMX53)	:= 0x70000100
+initrd_phys-$(CONFIG_SOC_IMX53)	:= 0x70800000
+
 zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
 params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
 initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
diff --git a/arch/arm/mach-imx/clock-mx51-mx53.c b/arch/arm/mach-imx/clock-mx51-mx53.c
new file mode 100644
index 0000000..0847050
--- /dev/null
+++ b/arch/arm/mach-imx/clock-mx51-mx53.c
@@ -0,0 +1,1675 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm-regs-imx5.h"
+
+/* External clock values passed-in by the board code */
+static unsigned long external_high_reference, external_low_reference;
+static unsigned long oscillator_reference, ckih2_reference;
+
+static struct clk osc_clk;
+static struct clk pll1_main_clk;
+static struct clk pll1_sw_clk;
+static struct clk pll2_sw_clk;
+static struct clk pll3_sw_clk;
+static struct clk mx53_pll4_sw_clk;
+static struct clk lp_apm_clk;
+static struct clk periph_apm_clk;
+static struct clk ahb_clk;
+static struct clk ipg_clk;
+static struct clk usboh3_clk;
+static struct clk emi_fast_clk;
+static struct clk ipu_clk;
+static struct clk mipi_hsc1_clk;
+static struct clk esdhc1_clk;
+static struct clk esdhc2_clk;
+static struct clk esdhc3_mx53_clk;
+
+#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
+
+/* calculate best pre and post dividers to get the required divider */
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
+	u32 max_pre, u32 max_post)
+{
+	if (div >= max_pre * max_post) {
+		*pre = max_pre;
+		*post = max_post;
+	} else if (div >= max_pre) {
+		u32 min_pre, temp_pre, old_err, err;
+		min_pre = DIV_ROUND_UP(div, max_post);
+		old_err = max_pre;
+		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
+			err = div % temp_pre;
+			if (err == 0) {
+				*pre = temp_pre;
+				break;
+			}
+			err = temp_pre - err;
+			if (err < old_err) {
+				old_err = err;
+				*pre = temp_pre;
+			}
+		}
+		*post = DIV_ROUND_UP(div, *pre);
+	} else {
+		*pre = div;
+		*post = 1;
+	}
+}
+
+static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
+{
+	u32 reg = __raw_readl(clk->enable_reg);
+
+	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
+	reg |= mode << clk->enable_shift;
+
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_ccgr_enable(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
+	return 0;
+}
+
+static void _clk_ccgr_disable(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
+}
+
+static int _clk_ccgr_enable_inrun(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+	return 0;
+}
+
+static void _clk_ccgr_disable_inwait(struct clk *clk)
+{
+	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
+}
+
+/*
+ * For the 4-to-1 muxed input clock
+ */
+static inline u32 _get_mux(struct clk *parent, struct clk *m0,
+			   struct clk *m1, struct clk *m2, struct clk *m3)
+{
+	if (parent == m0)
+		return 0;
+	else if (parent == m1)
+		return 1;
+	else if (parent == m2)
+		return 2;
+	else if (parent == m3)
+		return 3;
+	else
+		BUG();
+
+	return -EINVAL;
+}
+
+static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
+{
+	if (pll == &pll1_main_clk)
+		return MX51_DPLL1_BASE;
+	else if (pll == &pll2_sw_clk)
+		return MX51_DPLL2_BASE;
+	else if (pll == &pll3_sw_clk)
+		return MX51_DPLL3_BASE;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
+{
+	if (pll == &pll1_main_clk)
+		return MX53_DPLL1_BASE;
+	else if (pll == &pll2_sw_clk)
+		return MX53_DPLL2_BASE;
+	else if (pll == &pll3_sw_clk)
+		return MX53_DPLL3_BASE;
+	else if (pll == &mx53_pll4_sw_clk)
+		return MX53_DPLL4_BASE;
+	else
+		BUG();
+
+	return NULL;
+}
+
+static inline void __iomem *_get_pll_base(struct clk *pll)
+{
+	if (cpu_is_mx51())
+		return _mx51_get_pll_base(pll);
+	else
+		return _mx53_get_pll_base(pll);
+}
+
+static unsigned long clk_pll_get_rate(struct clk *clk)
+{
+	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+	void __iomem *pllbase;
+	s64 temp;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	pllbase = _get_pll_base(clk);
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+	if (pll_hfsm == 0) {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+	} else {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+	mfi = (mfi <= 5) ? 5 : mfi;
+	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+	/* Sign extend to 32-bits */
+	if (mfn >= 0x04000000) {
+		mfn |= 0xFC000000;
+		mfn_abs = -mfn;
+	}
+
+	ref_clk = 2 * parent_rate;
+	if (dbl != 0)
+		ref_clk *= 2;
+
+	ref_clk /= (pdf + 1);
+	temp = (u64) ref_clk * mfn_abs;
+	do_div(temp, mfd + 1);
+	if (mfn < 0)
+		temp = -temp;
+	temp = (ref_clk * mfi) + temp;
+
+	return temp;
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	void __iomem *pllbase;
+
+	long mfi, pdf, mfn, mfd = 999999;
+	s64 temp64;
+	unsigned long quad_parent_rate;
+	unsigned long pll_hfsm, dp_ctl;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	pllbase = _get_pll_base(clk);
+
+	quad_parent_rate = 4 * parent_rate;
+	pdf = mfi = -1;
+	while (++pdf < 16 && mfi < 5)
+		mfi = rate * (pdf+1) / quad_parent_rate;
+	if (mfi > 15)
+		return -EINVAL;
+	pdf--;
+
+	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
+	do_div(temp64, quad_parent_rate/1000000);
+	mfn = (long)temp64;
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	/* use dpdck0_2 */
+	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	if (pll_hfsm == 0) {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+	} else {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+
+	return 0;
+}
+
+static int _clk_pll_enable(struct clk *clk)
+{
+	u32 reg;
+	void __iomem *pllbase;
+	int i = 0;
+
+	pllbase = _get_pll_base(clk);
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	if (reg & MXC_PLL_DP_CTL_UPEN)
+		return 0;
+
+	reg |= MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+		if (reg & MXC_PLL_DP_CTL_LRF)
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: pll locking failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void _clk_pll_disable(struct clk *clk)
+{
+	u32 reg;
+	void __iomem *pllbase;
+
+	pllbase = _get_pll_base(clk);
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, step;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	/* When switching from pll_main_clk to a bypass clock, first select a
+	 * multiplexed clock in 'step_sel', then shift the glitchless mux
+	 * 'pll1_sw_clk_sel'.
+	 *
+	 * When switching back, do it in reverse order
+	 */
+	if (parent == &pll1_main_clk) {
+		/* Switch to pll1_main_clk */
+		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* step_clk mux switched to lp_apm, to save power. */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
+				MXC_CCM_CCSR_STEP_SEL_OFFSET);
+	} else {
+		if (parent == &lp_apm_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
+		} else  if (parent == &pll2_sw_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
+		} else  if (parent == &pll3_sw_clk) {
+			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
+		} else
+			return -EINVAL;
+
+		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
+		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
+
+		__raw_writel(reg, MXC_CCM_CCSR);
+		/* Switch to step_clk */
+		reg = __raw_readl(MXC_CCM_CCSR);
+		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+	}
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
+}
+
+static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (clk->parent == &pll2_sw_clk) {
+		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
+	} else if (clk->parent == &pll3_sw_clk) {
+		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
+		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
+	} else
+		div = 1;
+	return parent_rate / div;
+}
+
+static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CCSR);
+
+	if (parent == &pll2_sw_clk)
+		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+	else
+		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+	return 0;
+}
+
+static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	if (parent == &osc_clk)
+		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CCSR);
+
+	return 0;
+}
+
+static unsigned long clk_cpu_get_rate(struct clk *clk)
+{
+	u32 cacrr, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+	cacrr = __raw_readl(MXC_CCM_CACRR);
+	div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
+
+	return parent_rate / div;
+}
+
+static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, cpu_podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+	cpu_podf = parent_rate / rate - 1;
+	/* use post divider to change freq */
+	reg = __raw_readl(MXC_CCM_CACRR);
+	reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
+	reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CACRR);
+
+	return 0;
+}
+
+static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, mux;
+	int i = 0;
+
+	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
+
+	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(MXC_CCM_CDHIPR);
+		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: Set parent for periph_apm clock failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+
+	if (parent == &pll2_sw_clk)
+		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else if (parent == &periph_apm_clk)
+		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
+	else
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	return 0;
+}
+
+static struct clk main_bus_clk = {
+	.parent = &pll2_sw_clk,
+	.set_parent = _clk_main_bus_set_parent,
+};
+
+static unsigned long clk_ahb_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
+	       MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
+	return parent_rate / div;
+}
+
+
+static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+	int i = 0;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
+	reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(MXC_CCM_CDHIPR);
+		if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: clk_ahb_set_rate failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static unsigned long _clk_ahb_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	div = parent_rate / rate;
+	if (div > 8)
+		div = 8;
+	else if (div == 0)
+		div++;
+	return parent_rate / div;
+}
+
+
+static int _clk_max_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+
+	/* Handshake with MAX when LPM is entered. */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	if (cpu_is_mx51())
+		reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	else if (cpu_is_mx53())
+		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void _clk_max_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable_inwait(clk);
+
+	/* No Handshake with MAX when LPM is entered as its disabled. */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	if (cpu_is_mx51())
+		reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	else if (cpu_is_mx53())
+		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static unsigned long clk_ipg_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
+	       MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
+
+	return parent_rate / div;
+}
+
+static unsigned long clk_ipg_per_get_rate(struct clk *clk)
+{
+	u32 reg, prediv1, prediv2, podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
+		/* the main_bus_clk is the one before the DVFS engine */
+		reg = __raw_readl(MXC_CCM_CBCDR);
+		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
+			   MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
+		prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
+			   MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
+		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
+			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
+		return parent_rate / (prediv1 * prediv2 * podf);
+	} else if (clk->parent == &ipg_clk)
+		return parent_rate;
+	else
+		BUG();
+}
+
+static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CBCMR);
+
+	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+
+	if (parent == &ipg_clk)
+		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
+	else if (parent == &lp_apm_clk)
+		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
+	else if (parent != &main_bus_clk)
+		return -EINVAL;
+
+	__raw_writel(reg, MXC_CCM_CBCMR);
+
+	return 0;
+}
+
+#define clk_nfc_set_parent	NULL
+
+static unsigned long clk_nfc_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
+	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
+	rate = clk_get_rate(clk->parent) / div;
+	WARN_ON(rate == 0);
+	return rate;
+}
+
+static unsigned long clk_nfc_round_rate(struct clk *clk,
+						unsigned long rate)
+{
+	u32 div;
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+
+	if (!rate)
+		return -EINVAL;
+
+	div = parent_rate / rate;
+
+	if (parent_rate % rate)
+		div++;
+
+	if (div > 8)
+		return -EINVAL;
+
+	return parent_rate / div;
+
+}
+
+static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (div == 0)
+		div++;
+	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
+	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
+	__raw_writel(reg, MXC_CCM_CBCDR);
+
+	while (__raw_readl(MXC_CCM_CDHIPR) &
+			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
+	}
+
+	return 0;
+}
+
+static unsigned long get_high_reference_clock_rate(struct clk *clk)
+{
+	return external_high_reference;
+}
+
+static unsigned long get_low_reference_clock_rate(struct clk *clk)
+{
+	return external_low_reference;
+}
+
+static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
+{
+	return oscillator_reference;
+}
+
+static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
+{
+	return ckih2_reference;
+}
+
+static unsigned long clk_emi_slow_get_rate(struct clk *clk)
+{
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
+	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+	u32 reg, div;
+
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
+		MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
+	rate = clk_get_rate(clk->parent) / div;
+
+	return rate;
+}
+
+/* External high frequency clock */
+static struct clk ckih_clk = {
+	.get_rate = get_high_reference_clock_rate,
+};
+
+static struct clk ckih2_clk = {
+	.get_rate = get_ckih2_reference_clock_rate,
+};
+
+static struct clk osc_clk = {
+	.get_rate = get_oscillator_reference_clock_rate,
+};
+
+/* External low frequency (32kHz) clock */
+static struct clk ckil_clk = {
+	.get_rate = get_low_reference_clock_rate,
+};
+
+static struct clk pll1_main_clk = {
+	.parent = &osc_clk,
+	.get_rate = clk_pll_get_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* Clock tree block diagram (WIP):
+ * 	CCM: Clock Controller Module
+ *
+ * PLL output -> |
+ *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
+ * PLL bypass -> |
+ *
+ */
+
+/* PLL1 SW supplies to ARM core */
+static struct clk pll1_sw_clk = {
+	.parent = &pll1_main_clk,
+	.set_parent = _clk_pll1_sw_set_parent,
+	.get_rate = clk_pll1_sw_get_rate,
+};
+
+/* PLL2 SW supplies to AXI/AHB/IP buses */
+static struct clk pll2_sw_clk = {
+	.parent = &osc_clk,
+	.get_rate = clk_pll_get_rate,
+	.set_rate = _clk_pll_set_rate,
+	.set_parent = _clk_pll2_sw_set_parent,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
+static struct clk pll3_sw_clk = {
+	.parent = &osc_clk,
+	.set_rate = _clk_pll_set_rate,
+	.get_rate = clk_pll_get_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
+static struct clk mx53_pll4_sw_clk = {
+	.parent = &osc_clk,
+	.set_rate = _clk_pll_set_rate,
+	.enable = _clk_pll_enable,
+	.disable = _clk_pll_disable,
+};
+
+/* Low-power Audio Playback Mode clock */
+static struct clk lp_apm_clk = {
+	.parent = &osc_clk,
+	.set_parent = _clk_lp_apm_set_parent,
+};
+
+static struct clk periph_apm_clk = {
+	.parent = &pll1_sw_clk,
+	.set_parent = _clk_periph_apm_set_parent,
+};
+
+static struct clk cpu_clk = {
+	.parent = &pll1_sw_clk,
+	.get_rate = clk_cpu_get_rate,
+	.set_rate = clk_cpu_set_rate,
+};
+
+static struct clk ahb_clk = {
+	.parent = &main_bus_clk,
+	.get_rate = clk_ahb_get_rate,
+	.set_rate = _clk_ahb_set_rate,
+	.round_rate = _clk_ahb_round_rate,
+};
+
+static struct clk iim_clk = {
+	.parent = &ipg_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
+};
+
+/* Main IP interface clock for access to registers */
+static struct clk ipg_clk = {
+	.parent = &ahb_clk,
+	.get_rate = clk_ipg_get_rate,
+};
+
+static struct clk ipg_perclk = {
+	.parent = &lp_apm_clk,
+	.get_rate = clk_ipg_per_get_rate,
+	.set_parent = _clk_ipg_per_set_parent,
+};
+
+static struct clk ahb_max_clk = {
+	.parent = &ahb_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+	.enable = _clk_max_enable,
+	.disable = _clk_max_disable,
+};
+
+static struct clk aips_tz1_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk aips_tz2_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk gpc_dvfs_clk = {
+	.enable_reg = MXC_CCM_CCGR5,
+	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
+};
+
+static struct clk gpt_32k_clk = {
+	.id = 0,
+	.parent = &ckil_clk,
+};
+
+static struct clk dummy_clk = {
+	.id = 0,
+};
+
+static struct clk emi_slow_clk = {
+	.parent = &pll2_sw_clk,
+	.enable_reg = MXC_CCM_CCGR5,
+	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+	.get_rate = clk_emi_slow_get_rate,
+};
+
+static int clk_ipu_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+
+	/* Enable handshake with IPU when certain clock rates are changed */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	/* Enable handshake with IPU when LPM is entered */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void clk_ipu_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable(clk);
+
+	/* Disable handshake with IPU whe dividers are changed */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg |= MXC_CCM_CCDR_IPU_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	/* Disable handshake with IPU when LPM is entered */
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk ahbmux1_clk = {
+	.parent = &ahb_clk,
+	.secondary = &ahb_max_clk,
+	.enable_reg = MXC_CCM_CCGR0,
+	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable_inwait,
+};
+
+static struct clk ipu_sec_clk = {
+	.parent = &emi_fast_clk,
+	.secondary = &ahbmux1_clk,
+};
+
+static struct clk ddr_hf_clk = {
+	.parent = &pll1_sw_clk,
+	.get_rate = _clk_ddr_hf_get_rate,
+};
+
+static struct clk ddr_clk = {
+	.parent = &ddr_hf_clk,
+};
+
+/* clock definitions for MIPI HSC unit which has been removed
+ * from documentation, but not from hardware
+ */
+static int _clk_hsc_enable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_enable(clk);
+	/* Handshake with IPU when certain clock rates are changed. */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+
+	return 0;
+}
+
+static void _clk_hsc_disable(struct clk *clk)
+{
+	u32 reg;
+
+	_clk_ccgr_disable(clk);
+	/* No handshake with HSC as its not enabled. */
+	reg = __raw_readl(MXC_CCM_CCDR);
+	reg |= MXC_CCM_CCDR_HSC_HS_MASK;
+	__raw_writel(reg, MXC_CCM_CCDR);
+
+	reg = __raw_readl(MXC_CCM_CLPCR);
+	reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
+	__raw_writel(reg, MXC_CCM_CLPCR);
+}
+
+static struct clk mipi_hsp_clk = {
+	.parent = &ipu_clk,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
+	.enable = _clk_hsc_enable,
+	.disable = _clk_hsc_disable,
+	.secondary = &mipi_hsc1_clk,
+};
+
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.round_rate	= pfx##_round_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_ccgr_enable,	\
+		.disable	= _clk_ccgr_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_max_enable,	\
+		.disable	= _clk_max_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
+#define CLK_GET_RATE(name, nr, bitsname)				\
+static unsigned long clk_##name##_get_rate(struct clk *clk)		\
+{									\
+	u32 reg, pred, podf;						\
+									\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
+	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+									\
+	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
+			(pred + 1) * (podf + 1));			\
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)				\
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	u32 reg, mux;							\
+									\
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
+			&pll3_sw_clk, &lp_apm_clk);			\
+	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
+		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
+	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
+									\
+	return 0;							\
+}
+
+#define CLK_SET_RATE(name, nr, bitsname)				\
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
+{									\
+	u32 reg, div, parent_rate;					\
+	u32 pre = 0, post = 0;						\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div = parent_rate / rate;					\
+									\
+	if ((parent_rate / div) != rate)				\
+		return -EINVAL;						\
+									\
+	__calc_pre_post_dividers(div, &pre, &post,			\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
+		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
+									\
+	/* Set sdhc1 clock divider */					\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
+		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
+		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
+	reg |= (post - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+	reg |= (pre - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
+									\
+	return 0;							\
+}
+
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
+
+static struct clk uart_root_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_uart_get_rate,
+	.set_parent = clk_uart_set_parent,
+};
+
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
+
+static struct clk usboh3_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_usboh3_get_rate,
+	.set_parent = clk_usboh3_set_parent,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
+};
+
+static struct clk usb_ahb_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
+};
+
+static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
+
+	if (parent == &pll3_sw_clk)
+		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
+
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static struct clk usb_phy1_clk = {
+	.parent = &pll3_sw_clk,
+	.set_parent = clk_usb_phy1_set_parent,
+	.enable = _clk_ccgr_enable,
+	.enable_reg = MXC_CCM_CCGR2,
+	.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+	.disable = _clk_ccgr_disable,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
+
+static struct clk ecspi_main_clk = {
+	.parent = &pll3_sw_clk,
+	.get_rate = clk_ecspi_get_rate,
+	.set_parent = clk_ecspi_set_parent,
+};
+
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+/* mx51 specific */
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
+static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+/* mx53 specific */
+static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+
+static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
+	static struct clk name = {					\
+		.id		= i,					\
+		.enable_reg	= er,					\
+		.enable_shift	= es,					\
+		.get_rate	= gr,					\
+		.set_rate	= sr,					\
+		.enable		= e,					\
+		.disable	= d,					\
+		.parent		= p,					\
+		.secondary	= s,					\
+	}
+
+#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
+	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
+
+/* Shared peripheral bus arbiter */
+DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+
+/* UART */
+DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
+	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
+DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &ipg_clk, &spba_clk);
+DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
+DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
+DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
+DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
+DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
+	NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
+
+/* GPT */
+DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
+
+DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
+
+/* I2C */
+DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
+DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &ipg_perclk, NULL);
+
+/* FEC */
+DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
+	NULL,  NULL, &ipg_clk, NULL);
+
+/* NFC */
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+	clk_nfc, &emi_slow_clk, NULL);
+
+/* SSI */
+DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
+DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
+DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
+	NULL, NULL, &ipg_clk, NULL);
+DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
+	NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
+
+/* eCSPI */
+DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &spba_clk);
+DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
+DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
+		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
+		&ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
+		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
+
+/* CSPI */
+DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
+		NULL, NULL, &ipg_clk, &aips_tz2_clk);
+DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
+		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
+
+/* SDMA */
+DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
+		NULL, NULL, &ahb_clk, NULL);
+
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+
+/* mx51 specific */
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc3_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc3_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+static struct clk esdhc4_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
+/* mx53 specific */
+static struct clk esdhc2_mx53_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc2_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+
+DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
+	clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc4_mx53_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
+static struct clk sata_clk = {
+	.parent = &ipg_clk,
+	.enable = _clk_max_enable,
+	.enable_reg = MXC_CCM_CCGR4,
+	.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+	.disable = _clk_max_disable,
+};
+
+static struct clk ahci_phy_clk = {
+	.parent = &usb_phy1_clk,
+};
+
+static struct clk ahci_dma_clk = {
+	.parent = &ahb_clk,
+};
+
+DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
+DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
+
+/* IPU */
+DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
+	NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
+
+DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
+		NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
+		&ddr_clk, NULL);
+
+DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
+		NULL, NULL, &pll3_sw_clk, NULL);
+DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
+		NULL, NULL, &pll3_sw_clk, NULL);
+
+/* PATA */
+DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
+		NULL, NULL, &ipg_clk, &spba_clk);
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c,   \
+       },
+
+static struct clk_lookup mx51_lookups[] = {
+	/* i.mx51 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+	/* i.mx51 has the i.mx27 type fec */
+	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
+	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+	/* i.mx51 has the i.mx35 type sdma */
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
+	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
+	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+	/* i.mx51 has the i.mx35 type cspi */
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
+	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+	_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
+	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+};
+
+static struct clk_lookup mx53_lookups[] = {
+	/* i.mx53 has the i.mx21 type uart */
+	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
+	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
+	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
+	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
+	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
+	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
+	/* i.mx53 has the i.mx25 type fec */
+	_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
+	/* i.mx53 has the i.mx51 type ecspi */
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
+	/* i.mx53 has the i.mx25 type cspi */
+	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
+	/* i.mx53 has the i.mx35 type sdma */
+	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
+	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
+	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
+	_REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
+};
+
+static void clk_tree_init(void)
+{
+	u32 reg;
+
+	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
+
+	/*
+	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
+	 * 8MHz, its derived from lp_apm.
+	 *
+	 * FIXME: Verify if true for all boards
+	 */
+	reg = __raw_readl(MXC_CCM_CBCDR);
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
+	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
+	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
+	__raw_writel(reg, MXC_CCM_CBCDR);
+}
+
+int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
+			unsigned long ckih1, unsigned long ckih2)
+{
+	int i;
+
+	external_low_reference = ckil;
+	external_high_reference = ckih1;
+	ckih2_reference = ckih2;
+	oscillator_reference = osc;
+
+	for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
+		clkdev_add(&mx51_lookups[i]);
+
+	clk_tree_init();
+
+	clk_enable(&cpu_clk);
+	clk_enable(&main_bus_clk);
+
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX51", mx51_revision());
+	clk_disable(&iim_clk);
+
+	/* move usb_phy_clk to 24MHz */
+	clk_set_parent(&usb_phy1_clk, &osc_clk);
+
+	/* set the usboh3_clk parent to pll2_sw_clk */
+	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(&esdhc1_clk, 166250000);
+	clk_set_rate(&esdhc2_clk, 166250000);
+
+	/* System timer */
+	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+		MX51_INT_GPT);
+	return 0;
+}
+
+int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
+			unsigned long ckih1, unsigned long ckih2)
+{
+	int i;
+
+	external_low_reference = ckil;
+	external_high_reference = ckih1;
+	ckih2_reference = ckih2;
+	oscillator_reference = osc;
+
+	for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
+		clkdev_add(&mx53_lookups[i]);
+
+	clk_tree_init();
+
+	clk_set_parent(&uart_root_clk, &pll3_sw_clk);
+	clk_enable(&cpu_clk);
+	clk_enable(&main_bus_clk);
+
+	clk_enable(&iim_clk);
+	imx_print_silicon_rev("i.MX53", mx53_revision());
+	clk_disable(&iim_clk);
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 200MHZ*/
+	clk_set_rate(&esdhc1_clk, 200000000);
+	clk_set_rate(&esdhc3_mx53_clk, 200000000);
+
+	/* System timer */
+	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+		MX53_INT_GPT);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
+				   unsigned long *ckih1, unsigned long *ckih2)
+{
+	struct device_node *np;
+
+	/* retrieve the freqency of fixed clocks from device tree */
+	for_each_compatible_node(np, NULL, "fixed-clock") {
+		u32 rate;
+		if (of_property_read_u32(np, "clock-frequency", &rate))
+			continue;
+
+		if (of_device_is_compatible(np, "fsl,imx-ckil"))
+			*ckil = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-osc"))
+			*osc = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
+			*ckih1 = rate;
+		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
+			*ckih2 = rate;
+	}
+}
+
+int __init mx51_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
+}
+
+int __init mx53_clocks_init_dt(void)
+{
+	unsigned long ckil, osc, ckih1, ckih2;
+
+	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
+	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
+}
+#endif
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
new file mode 100644
index 0000000..5e2e7a8
--- /dev/null
+++ b/arch/arm/mach-imx/cpu-imx5.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * This file contains the CPU initialization code.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+static int mx5_cpu_rev = -1;
+
+#define IIM_SREV 0x24
+#define MX50_HW_ADADIG_DIGPROG	0xB0
+
+static int get_mx51_srev(void)
+{
+	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
+	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+	switch (rev) {
+	case 0x0:
+		return IMX_CHIP_REVISION_2_0;
+	case 0x10:
+		return IMX_CHIP_REVISION_3_0;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx51
+ */
+int mx51_revision(void)
+{
+	if (!cpu_is_mx51())
+		return -EINVAL;
+
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx51_srev();
+
+	return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx51_revision);
+
+#ifdef CONFIG_NEON
+
+/*
+ * All versions of the silicon before Rev. 3 have broken NEON implementations.
+ * Dependent on link order - so the assumption is that vfp_init is called
+ * before us.
+ */
+static int __init mx51_neon_fixup(void)
+{
+	if (!cpu_is_mx51())
+		return 0;
+
+	if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+			(elf_hwcap & HWCAP_NEON)) {
+		elf_hwcap &= ~HWCAP_NEON;
+		pr_info("Turning off NEON support, detected broken NEON implementation\n");
+	}
+	return 0;
+}
+
+late_initcall(mx51_neon_fixup);
+#endif
+
+static int get_mx53_srev(void)
+{
+	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
+	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
+
+	switch (rev) {
+	case 0x0:
+		return IMX_CHIP_REVISION_1_0;
+	case 0x2:
+		return IMX_CHIP_REVISION_2_0;
+	case 0x3:
+		return IMX_CHIP_REVISION_2_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx53
+ */
+int mx53_revision(void)
+{
+	if (!cpu_is_mx53())
+		return -EINVAL;
+
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx53_srev();
+
+	return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx53_revision);
+
+static int get_mx50_srev(void)
+{
+	void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
+	u32 rev;
+
+	if (!anatop) {
+		mx5_cpu_rev = -EINVAL;
+		return 0;
+	}
+
+	rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
+	rev &= 0xff;
+
+	iounmap(anatop);
+	if (rev == 0x0)
+		return IMX_CHIP_REVISION_1_0;
+	else if (rev == 0x1)
+		return IMX_CHIP_REVISION_1_1;
+	return 0;
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx50
+ */
+int mx50_revision(void)
+{
+	if (!cpu_is_mx50())
+		return -EINVAL;
+
+	if (mx5_cpu_rev == -1)
+		mx5_cpu_rev = get_mx50_srev();
+
+	return mx5_cpu_rev;
+}
+EXPORT_SYMBOL(mx50_revision);
+
+static int __init post_cpu_init(void)
+{
+	unsigned int reg;
+	void __iomem *base;
+
+	if (cpu_is_mx51() || cpu_is_mx53()) {
+		if (cpu_is_mx51())
+			base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
+		else
+			base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
+
+		__raw_writel(0x0, base + 0x40);
+		__raw_writel(0x0, base + 0x44);
+		__raw_writel(0x0, base + 0x48);
+		__raw_writel(0x0, base + 0x4C);
+		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+		__raw_writel(reg, base + 0x50);
+
+		if (cpu_is_mx51())
+			base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
+		else
+			base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
+
+		__raw_writel(0x0, base + 0x40);
+		__raw_writel(0x0, base + 0x44);
+		__raw_writel(0x0, base + 0x48);
+		__raw_writel(0x0, base + 0x4C);
+		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
+		__raw_writel(reg, base + 0x50);
+	}
+
+	return 0;
+}
+
+postcore_initcall(post_cpu_init);
diff --git a/arch/arm/mach-imx/cpu_op-mx51.c b/arch/arm/mach-imx/cpu_op-mx51.c
new file mode 100644
index 0000000..9d34c3d
--- /dev/null
+++ b/arch/arm/mach-imx/cpu_op-mx51.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/types.h>
+#include <mach/hardware.h>
+#include <linux/kernel.h>
+
+static struct cpu_op mx51_cpu_op[] = {
+	{
+	.cpu_rate = 160000000,},
+	{
+	.cpu_rate = 800000000,},
+};
+
+struct cpu_op *mx51_get_cpu_op(int *op)
+{
+	*op = ARRAY_SIZE(mx51_cpu_op);
+	return mx51_cpu_op;
+}
diff --git a/arch/arm/mach-imx/cpu_op-mx51.h b/arch/arm/mach-imx/cpu_op-mx51.h
new file mode 100644
index 0000000..97477fe
--- /dev/null
+++ b/arch/arm/mach-imx/cpu_op-mx51.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h
new file mode 100644
index 0000000..5e11ba7
--- /dev/null
+++ b/arch/arm/mach-imx/crm-regs-imx5.h
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+
+#define MX51_CCM_BASE		MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
+#define MX51_DPLL1_BASE		MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
+#define MX51_DPLL2_BASE		MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
+#define MX51_DPLL3_BASE		MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
+#define MX51_CORTEXA8_BASE	MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
+#define MX51_GPC_BASE		MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
+
+/*MX53*/
+#define MX53_CCM_BASE		MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
+#define MX53_DPLL1_BASE		MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
+#define MX53_DPLL2_BASE		MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
+#define MX53_DPLL3_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+
+/* PLL Register Offsets */
+#define MXC_PLL_DP_CTL			0x00
+#define MXC_PLL_DP_CONFIG		0x04
+#define MXC_PLL_DP_OP			0x08
+#define MXC_PLL_DP_MFD			0x0C
+#define MXC_PLL_DP_MFN			0x10
+#define MXC_PLL_DP_MFNMINUS		0x14
+#define MXC_PLL_DP_MFNPLUS		0x18
+#define MXC_PLL_DP_HFS_OP		0x1C
+#define MXC_PLL_DP_HFS_MFD		0x20
+#define MXC_PLL_DP_HFS_MFN		0x24
+#define MXC_PLL_DP_MFN_TOGC		0x28
+#define MXC_PLL_DP_DESTAT		0x2c
+
+/* PLL Register Bit definitions */
+#define MXC_PLL_DP_CTL_MUL_CTRL		0x2000
+#define MXC_PLL_DP_CTL_DPDCK0_2_EN	0x1000
+#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET	12
+#define MXC_PLL_DP_CTL_ADE		0x800
+#define MXC_PLL_DP_CTL_REF_CLK_DIV	0x400
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK	(3 << 8)
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET	8
+#define MXC_PLL_DP_CTL_HFSM		0x80
+#define MXC_PLL_DP_CTL_PRE		0x40
+#define MXC_PLL_DP_CTL_UPEN		0x20
+#define MXC_PLL_DP_CTL_RST		0x10
+#define MXC_PLL_DP_CTL_RCP		0x8
+#define MXC_PLL_DP_CTL_PLM		0x4
+#define MXC_PLL_DP_CTL_BRM0		0x2
+#define MXC_PLL_DP_CTL_LRF		0x1
+
+#define MXC_PLL_DP_CONFIG_BIST		0x8
+#define MXC_PLL_DP_CONFIG_SJC_CE	0x4
+#define MXC_PLL_DP_CONFIG_AREN		0x2
+#define MXC_PLL_DP_CONFIG_LDREQ		0x1
+
+#define MXC_PLL_DP_OP_MFI_OFFSET	4
+#define MXC_PLL_DP_OP_MFI_MASK		(0xF << 4)
+#define MXC_PLL_DP_OP_PDF_OFFSET	0
+#define MXC_PLL_DP_OP_PDF_MASK		0xF
+
+#define MXC_PLL_DP_MFD_OFFSET		0
+#define MXC_PLL_DP_MFD_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_OFFSET		0x0
+#define MXC_PLL_DP_MFN_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_TOGC_TOG_DIS	(1 << 17)
+#define MXC_PLL_DP_MFN_TOGC_TOG_EN	(1 << 16)
+#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET	0x0
+#define MXC_PLL_DP_MFN_TOGC_CNT_MASK	0xFFFF
+
+#define MXC_PLL_DP_DESTAT_TOG_SEL	(1 << 31)
+#define MXC_PLL_DP_DESTAT_MFN		0x07FFFFFF
+
+/* Register addresses of CCM*/
+#define MXC_CCM_CCR		(MX51_CCM_BASE + 0x00)
+#define MXC_CCM_CCDR		(MX51_CCM_BASE + 0x04)
+#define MXC_CCM_CSR		(MX51_CCM_BASE + 0x08)
+#define MXC_CCM_CCSR		(MX51_CCM_BASE + 0x0C)
+#define MXC_CCM_CACRR		(MX51_CCM_BASE + 0x10)
+#define MXC_CCM_CBCDR		(MX51_CCM_BASE + 0x14)
+#define MXC_CCM_CBCMR		(MX51_CCM_BASE + 0x18)
+#define MXC_CCM_CSCMR1		(MX51_CCM_BASE + 0x1C)
+#define MXC_CCM_CSCMR2		(MX51_CCM_BASE + 0x20)
+#define MXC_CCM_CSCDR1		(MX51_CCM_BASE + 0x24)
+#define MXC_CCM_CS1CDR		(MX51_CCM_BASE + 0x28)
+#define MXC_CCM_CS2CDR		(MX51_CCM_BASE + 0x2C)
+#define MXC_CCM_CDCDR		(MX51_CCM_BASE + 0x30)
+#define MXC_CCM_CHSCDR		(MX51_CCM_BASE + 0x34)
+#define MXC_CCM_CSCDR2		(MX51_CCM_BASE + 0x38)
+#define MXC_CCM_CSCDR3		(MX51_CCM_BASE + 0x3C)
+#define MXC_CCM_CSCDR4		(MX51_CCM_BASE + 0x40)
+#define MXC_CCM_CWDR		(MX51_CCM_BASE + 0x44)
+#define MXC_CCM_CDHIPR		(MX51_CCM_BASE + 0x48)
+#define MXC_CCM_CDCR		(MX51_CCM_BASE + 0x4C)
+#define MXC_CCM_CTOR		(MX51_CCM_BASE + 0x50)
+#define MXC_CCM_CLPCR		(MX51_CCM_BASE + 0x54)
+#define MXC_CCM_CISR		(MX51_CCM_BASE + 0x58)
+#define MXC_CCM_CIMR		(MX51_CCM_BASE + 0x5C)
+#define MXC_CCM_CCOSR		(MX51_CCM_BASE + 0x60)
+#define MXC_CCM_CGPR		(MX51_CCM_BASE + 0x64)
+#define MXC_CCM_CCGR0		(MX51_CCM_BASE + 0x68)
+#define MXC_CCM_CCGR1		(MX51_CCM_BASE + 0x6C)
+#define MXC_CCM_CCGR2		(MX51_CCM_BASE + 0x70)
+#define MXC_CCM_CCGR3		(MX51_CCM_BASE + 0x74)
+#define MXC_CCM_CCGR4		(MX51_CCM_BASE + 0x78)
+#define MXC_CCM_CCGR5		(MX51_CCM_BASE + 0x7C)
+#define MXC_CCM_CCGR6		(MX51_CCM_BASE + 0x80)
+#define MXC_CCM_CCGR7		(MX51_CCM_BASE + 0x84)
+
+#define MXC_CCM_CMEOR		(MX51_CCM_BASE + 0x84)
+
+/* Define the bits in register CCR */
+#define MXC_CCM_CCR_COSC_EN		(1 << 12)
+#define MXC_CCM_CCR_FPM_MULT_MASK	(1 << 11)
+#define MXC_CCM_CCR_CAMP2_EN		(1 << 10)
+#define MXC_CCM_CCR_CAMP1_EN		(1 << 9)
+#define MXC_CCM_CCR_FPM_EN		(1 << 8)
+#define MXC_CCM_CCR_OSCNT_OFFSET	(0)
+#define MXC_CCM_CCR_OSCNT_MASK	(0xFF)
+
+/* Define the bits in register CCDR */
+#define MXC_CCM_CCDR_HSC_HS_MASK	(0x1 << 18)
+#define MXC_CCM_CCDR_IPU_HS_MASK	(0x1 << 17)
+#define MXC_CCM_CCDR_EMI_HS_MASK	(0x1 << 16)
+
+/* Define the bits in register CSR */
+#define MXC_CCM_CSR_COSR_READY	(1 << 5)
+#define MXC_CCM_CSR_LVS_VALUE	(1 << 4)
+#define MXC_CCM_CSR_CAMP2_READY	(1 << 3)
+#define MXC_CCM_CSR_CAMP1_READY	(1 << 2)
+#define MXC_CCM_CSR_FPM_READY	(1 << 1)
+#define MXC_CCM_CSR_REF_EN_B	(1 << 0)
+
+/* Define the bits in register CCSR */
+#define MXC_CCM_CCSR_LP_APM_SEL		(0x1 << 9)
+#define MXC_CCM_CCSR_STEP_SEL_OFFSET	(7)
+#define MXC_CCM_CCSR_STEP_SEL_MASK	(0x3 << 7)
+#define MXC_CCM_CCSR_STEP_SEL_LP_APM	   0
+#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
+#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
+#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
+#define MXC_CCM_CCSR_PLL2_PODF_OFFSET	(5)
+#define MXC_CCM_CCSR_PLL2_PODF_MASK	(0x3 << 5)
+#define MXC_CCM_CCSR_PLL3_PODF_OFFSET	(3)
+#define MXC_CCM_CCSR_PLL3_PODF_MASK	(0x3 << 3)
+#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL	(1 << 2) /* 0: pll1_main_clk,
+						    1: step_clk */
+#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL	(1 << 1)
+#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL	(1 << 0)
+
+/* Define the bits in register CACRR */
+#define MXC_CCM_CACRR_ARM_PODF_OFFSET	(0)
+#define MXC_CCM_CACRR_ARM_PODF_MASK	(0x7)
+
+/* Define the bits in register CBCDR */
+#define MXC_CCM_CBCDR_EMI_CLK_SEL		(0x1 << 26)
+#define MXC_CCM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
+#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET		(30)
+#define MXC_CCM_CBCDR_DDR_HF_SEL		(0x1 << 30)
+#define MXC_CCM_CBCDR_DDR_PODF_OFFSET		(27)
+#define MXC_CCM_CBCDR_DDR_PODF_MASK		(0x7 << 27)
+#define MXC_CCM_CBCDR_EMI_PODF_OFFSET		(22)
+#define MXC_CCM_CBCDR_EMI_PODF_MASK		(0x7 << 22)
+#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET		(19)
+#define MXC_CCM_CBCDR_AXI_B_PODF_MASK		(0x7 << 19)
+#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET		(16)
+#define MXC_CCM_CBCDR_AXI_A_PODF_MASK		(0x7 << 16)
+#define MXC_CCM_CBCDR_NFC_PODF_OFFSET		(13)
+#define MXC_CCM_CBCDR_NFC_PODF_MASK		(0x7 << 13)
+#define MXC_CCM_CBCDR_AHB_PODF_OFFSET		(10)
+#define MXC_CCM_CBCDR_AHB_PODF_MASK		(0x7 << 10)
+#define MXC_CCM_CBCDR_IPG_PODF_OFFSET		(8)
+#define MXC_CCM_CBCDR_IPG_PODF_MASK		(0x3 << 8)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET	(6)
+#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK		(0x3 << 6)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET	(3)
+#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK		(0x7 << 3)
+#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET	(0)
+#define MXC_CCM_CBCDR_PERCLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CBCMR */
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET	(14)
+#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK	(0x3 << 14)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET	(12)
+#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK	(0x3 << 12)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET	(10)
+#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK		(0x3 << 10)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET	(8)
+#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK	(0x3 << 8)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET	(6)
+#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK	(0x3 << 6)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET	(4)
+#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK		(0x3 << 4)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET	(14)
+#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK	(0x3 << 14)
+#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL	(0x1 << 1)
+#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL	(0x1 << 0)
+
+/* Define the bits in register CSCMR1 */
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET		(30)
+#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK		(0x3 << 30)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET		(28)
+#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK		(0x3 << 28)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET		(26)
+#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL			(0x1 << 26)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET		(24)
+#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK		(0x3 << 24)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET		(22)
+#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK		(0x3 << 22)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
+#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
+#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
+#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
+#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK		(0x3 << 12)
+#define MXC_CCM_CSCMR1_SSI3_CLK_SEL			(0x1 << 11)
+#define MXC_CCM_CSCMR1_VPU_RCLK_SEL			(0x1 << 10)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET		(8)
+#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK		(0x3 << 8)
+#define MXC_CCM_CSCMR1_TVE_CLK_SEL			(0x1 << 7)
+#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL			(0x1 << 6)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET		(4)
+#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK		(0x3 << 4)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET		(2)
+#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK		(0x3 << 2)
+#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL		(0x1 << 1)
+#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL		(0x1)
+
+/* Define the bits in register CSCMR2 */
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)		(26+n*3)
+#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)		(0x7 << (26+n*3))
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET		(24)
+#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK		(0x3 << 24)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET		(22)
+#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK		(0x3 << 22)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET		(20)
+#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK			(0x3 << 20)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET		(18)
+#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK		(0x3 << 18)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET		(16)
+#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK		(0x3 << 16)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET		(14)
+#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK		(0x3 << 14)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET		(12)
+#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK		(0x3 << 12)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET		(10)
+#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK			(0x3 << 10)
+#define MXC_CCM_CSCMR2_SLIMBUS_COM			(0x1 << 9)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET		(6)
+#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK		(0x7 << 6)
+#define MXC_CCM_CSCMR2_SPDIF1_COM			(1 << 5)
+#define MXC_CCM_CSCMR2_SPDIF0_COM			(1 << 4)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET		(2)
+#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK		(0x3 << 2)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET		(0)
+#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK		(0x3)
+
+/* Define the bits in register CSCDR1 */
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET	(22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
+#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
+#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK		(0x3 << 14)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET	(11)
+#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK	(0x7 << 11)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET		(8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK		(0x7 << 8)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET		(6)
+#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK		(0x3 << 6)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET		(3)
+#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK		(0x7 << 3)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CS1CDR and CS2CDR */
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET		(22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK		(0x7 << 22)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET		(16)
+#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK		(0x3F << 16)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK		(0x3F)
+
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET		(22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK		(0x7 << 22)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET		(16)
+#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK		(0x3F << 16)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CDCDR */
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET		(28)
+#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK			(0x7 << 28)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET		(25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK		(0x7 << 25)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET		(19)
+#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK		(0x3F << 19)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK			(0x7 << 6)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET		(3)
+#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK			(0x7 << 3)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET		(0)
+#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK			(0x7)
+
+/* Define the bits in register CHSCCDR */
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET		(12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK		(0x7 << 12)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET		(6)
+#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK		(0x3F << 6)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET		(3)
+#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK		(0x7 << 3)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK		(0x7)
+
+/* Define the bits in register CSCDR2 */
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET		(25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK		(0x7 << 25)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET		(19)
+#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK		(0x3F << 19)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK		(0x3F)
+
+/* Define the bits in register CSCDR3 */
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET		(16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET		(9)
+#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET		(6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET		(0)
+#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CSCDR4 */
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET	(16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK		(0x7 << 16)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET	(9)
+#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK		(0x3F << 9)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET	(6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK		(0x7 << 6)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET	(0)
+#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK		(0x3F)
+
+/* Define the bits in register CDHIPR */
+#define MXC_CCM_CDHIPR_ARM_PODF_BUSY			(1 << 16)
+#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY		(1 << 8)
+#define MXC_CCM_CDHIPR_DDR_PODF_BUSY			(1 << 7)
+#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY			(1 << 6)
+#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY		(1 << 5)
+#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY	(1 << 4)
+#define MXC_CCM_CDHIPR_AHB_PODF_BUSY			(1 << 3)
+#define MXC_CCM_CDHIPR_EMI_PODF_BUSY			(1 << 2)
+#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY			(1 << 1)
+#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY			(1 << 0)
+
+/* Define the bits in register CDCR */
+#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER		(0x1 << 2)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET	(0)
+#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK		(0x3)
+
+/* Define the bits in register CLPCR */
+#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS		(0x1 << 23)
+#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS		(0x1 << 22)
+#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 21)
+#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 25)
+#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS	(0x1 << 20)
+#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS		(0x1 << 19)
+#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS		(0x1 << 18)
+#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS	(0x1 << 17)
+#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS	(0x1 << 16)
+#define MXC_CCM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET		(9)
+#define MXC_CCM_CLPCR_STBY_COUNT_MASK		(0x3 << 9)
+#define MXC_CCM_CLPCR_VSTBY			(0x1 << 8)
+#define MXC_CCM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define MXC_CCM_CLPCR_SBYOS			(0x1 << 6)
+#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET	(3)
+#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK		(0x3 << 3)
+#define MXC_CCM_CLPCR_LPM_OFFSET		(0)
+#define MXC_CCM_CLPCR_LPM_MASK			(0x3)
+
+/* Define the bits in register CISR */
+#define MXC_CCM_CISR_ARM_PODF_LOADED			(0x1 << 25)
+#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
+#define MXC_CCM_CISR_AHB_PODF_LOADED			(0x1 << 20)
+#define MXC_CCM_CISR_EMI_PODF_LOADED			(0x1 << 19)
+#define MXC_CCM_CISR_AXI_B_PODF_LOADED			(0x1 << 18)
+#define MXC_CCM_CISR_AXI_A_PODF_LOADED			(0x1 << 17)
+#define MXC_CCM_CISR_DIVIDER_LOADED			(0x1 << 16)
+#define MXC_CCM_CISR_COSC_READY				(0x1 << 6)
+#define MXC_CCM_CISR_CKIH2_READY			(0x1 << 5)
+#define MXC_CCM_CISR_CKIH_READY				(0x1 << 4)
+#define MXC_CCM_CISR_FPM_READY				(0x1 << 3)
+#define MXC_CCM_CISR_LRF_PLL3				(0x1 << 2)
+#define MXC_CCM_CISR_LRF_PLL2				(0x1 << 1)
+#define MXC_CCM_CISR_LRF_PLL1				(0x1)
+
+/* Define the bits in register CIMR */
+#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED		(0x1 << 25)
+#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
+#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED		(0x1 << 20)
+#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED		(0x1 << 19)
+#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED		(0x1 << 18)
+#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED		(0x1 << 17)
+#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED		(0x1 << 16)
+#define MXC_CCM_CIMR_MASK_COSC_READY			(0x1 << 5)
+#define MXC_CCM_CIMR_MASK_CKIH_READY			(0x1 << 4)
+#define MXC_CCM_CIMR_MASK_FPM_READY			(0x1 << 3)
+#define MXC_CCM_CIMR_MASK_LRF_PLL3			(0x1 << 2)
+#define MXC_CCM_CIMR_MASK_LRF_PLL2			(0x1 << 1)
+#define MXC_CCM_CIMR_MASK_LRF_PLL1			(0x1)
+
+/* Define the bits in register CCOSR */
+#define MXC_CCM_CCOSR_CKO2_EN_OFFSET			(0x1 << 24)
+#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET			(21)
+#define MXC_CCM_CCOSR_CKO2_DIV_MASK			(0x7 << 21)
+#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET			(16)
+#define MXC_CCM_CCOSR_CKO2_SEL_MASK			(0x1F << 16)
+#define MXC_CCM_CCOSR_CKOL_EN				(0x1 << 7)
+#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET			(4)
+#define MXC_CCM_CCOSR_CKOL_DIV_MASK			(0x7 << 4)
+#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET			(0)
+#define MXC_CCM_CCOSR_CKOL_SEL_MASK			(0xF)
+
+/* Define the bits in registers CGPR */
+#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE		(0x1 << 4)
+#define MXC_CCM_CGPR_FPM_SEL				(0x1 << 3)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET		(0)
+#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK		(0x7)
+
+/* Define the bits in registers CCGRx */
+#define MXC_CCM_CCGRx_CG_MASK				0x3
+#define MXC_CCM_CCGRx_MOD_OFF				0x0
+#define MXC_CCM_CCGRx_MOD_ON				0x3
+#define MXC_CCM_CCGRx_MOD_IDLE				0x1
+
+#define MXC_CCM_CCGRx_CG15_MASK				(0x3 << 30)
+#define MXC_CCM_CCGRx_CG14_MASK				(0x3 << 28)
+#define MXC_CCM_CCGRx_CG13_MASK				(0x3 << 26)
+#define MXC_CCM_CCGRx_CG12_MASK				(0x3 << 24)
+#define MXC_CCM_CCGRx_CG11_MASK				(0x3 << 22)
+#define MXC_CCM_CCGRx_CG10_MASK				(0x3 << 20)
+#define MXC_CCM_CCGRx_CG9_MASK				(0x3 << 18)
+#define MXC_CCM_CCGRx_CG8_MASK				(0x3 << 16)
+#define MXC_CCM_CCGRx_CG5_MASK				(0x3 << 10)
+#define MXC_CCM_CCGRx_CG4_MASK				(0x3 << 8)
+#define MXC_CCM_CCGRx_CG3_MASK				(0x3 << 6)
+#define MXC_CCM_CCGRx_CG2_MASK				(0x3 << 4)
+#define MXC_CCM_CCGRx_CG1_MASK				(0x3 << 2)
+#define MXC_CCM_CCGRx_CG0_MASK				(0x3 << 0)
+
+#define MXC_CCM_CCGRx_CG15_OFFSET			30
+#define MXC_CCM_CCGRx_CG14_OFFSET			28
+#define MXC_CCM_CCGRx_CG13_OFFSET			26
+#define MXC_CCM_CCGRx_CG12_OFFSET			24
+#define MXC_CCM_CCGRx_CG11_OFFSET			22
+#define MXC_CCM_CCGRx_CG10_OFFSET			20
+#define MXC_CCM_CCGRx_CG9_OFFSET			18
+#define MXC_CCM_CCGRx_CG8_OFFSET			16
+#define MXC_CCM_CCGRx_CG7_OFFSET			14
+#define MXC_CCM_CCGRx_CG6_OFFSET			12
+#define MXC_CCM_CCGRx_CG5_OFFSET			10
+#define MXC_CCM_CCGRx_CG4_OFFSET			8
+#define MXC_CCM_CCGRx_CG3_OFFSET			6
+#define MXC_CCM_CCGRx_CG2_OFFSET			4
+#define MXC_CCM_CCGRx_CG1_OFFSET			2
+#define MXC_CCM_CCGRx_CG0_OFFSET			0
+
+#define MXC_DPTC_LP_BASE	(MX51_GPC_BASE + 0x80)
+#define MXC_DPTC_GP_BASE	(MX51_GPC_BASE + 0x100)
+#define MXC_DVFS_CORE_BASE	(MX51_GPC_BASE + 0x180)
+#define MXC_DPTC_PER_BASE	(MX51_GPC_BASE + 0x1C0)
+#define MXC_PGC_IPU_BASE	(MX51_GPC_BASE + 0x220)
+#define MXC_PGC_VPU_BASE	(MX51_GPC_BASE + 0x240)
+#define MXC_PGC_GPU_BASE	(MX51_GPC_BASE + 0x260)
+#define MXC_SRPG_NEON_BASE	(MX51_GPC_BASE + 0x280)
+#define MXC_SRPG_ARM_BASE	(MX51_GPC_BASE + 0x2A0)
+#define MXC_SRPG_EMPGC0_BASE	(MX51_GPC_BASE + 0x2C0)
+#define MXC_SRPG_EMPGC1_BASE	(MX51_GPC_BASE + 0x2D0)
+#define MXC_SRPG_MEGAMIX_BASE	(MX51_GPC_BASE + 0x2E0)
+#define MXC_SRPG_EMI_BASE	(MX51_GPC_BASE + 0x300)
+
+/* CORTEXA8 platform */
+#define MXC_CORTEXA8_PLAT_PVID		(MX51_CORTEXA8_BASE + 0x0)
+#define MXC_CORTEXA8_PLAT_GPC		(MX51_CORTEXA8_BASE + 0x4)
+#define MXC_CORTEXA8_PLAT_PIC		(MX51_CORTEXA8_BASE + 0x8)
+#define MXC_CORTEXA8_PLAT_LPC		(MX51_CORTEXA8_BASE + 0xC)
+#define MXC_CORTEXA8_PLAT_NEON_LPC	(MX51_CORTEXA8_BASE + 0x10)
+#define MXC_CORTEXA8_PLAT_ICGC		(MX51_CORTEXA8_BASE + 0x14)
+#define MXC_CORTEXA8_PLAT_AMC		(MX51_CORTEXA8_BASE + 0x18)
+#define MXC_CORTEXA8_PLAT_NMC		(MX51_CORTEXA8_BASE + 0x20)
+#define MXC_CORTEXA8_PLAT_NMS		(MX51_CORTEXA8_BASE + 0x24)
+
+/* DVFS CORE */
+#define MXC_DVFSTHRS		(MXC_DVFS_CORE_BASE + 0x00)
+#define MXC_DVFSCOUN		(MXC_DVFS_CORE_BASE + 0x04)
+#define MXC_DVFSSIG1		(MXC_DVFS_CORE_BASE + 0x08)
+#define MXC_DVFSSIG0		(MXC_DVFS_CORE_BASE + 0x0C)
+#define MXC_DVFSGPC0		(MXC_DVFS_CORE_BASE + 0x10)
+#define MXC_DVFSGPC1		(MXC_DVFS_CORE_BASE + 0x14)
+#define MXC_DVFSGPBT		(MXC_DVFS_CORE_BASE + 0x18)
+#define MXC_DVFSEMAC		(MXC_DVFS_CORE_BASE + 0x1C)
+#define MXC_DVFSCNTR		(MXC_DVFS_CORE_BASE + 0x20)
+#define MXC_DVFSLTR0_0		(MXC_DVFS_CORE_BASE + 0x24)
+#define MXC_DVFSLTR0_1		(MXC_DVFS_CORE_BASE + 0x28)
+#define MXC_DVFSLTR1_0		(MXC_DVFS_CORE_BASE + 0x2C)
+#define MXC_DVFSLTR1_1		(MXC_DVFS_CORE_BASE + 0x30)
+#define MXC_DVFSPT0 		(MXC_DVFS_CORE_BASE + 0x34)
+#define MXC_DVFSPT1 		(MXC_DVFS_CORE_BASE + 0x38)
+#define MXC_DVFSPT2 		(MXC_DVFS_CORE_BASE + 0x3C)
+#define MXC_DVFSPT3 		(MXC_DVFS_CORE_BASE + 0x40)
+
+/* GPC */
+#define MXC_GPC_CNTR		(MX51_GPC_BASE + 0x0)
+#define MXC_GPC_PGR		(MX51_GPC_BASE + 0x4)
+#define MXC_GPC_VCR		(MX51_GPC_BASE + 0x8)
+#define MXC_GPC_ALL_PU		(MX51_GPC_BASE + 0xC)
+#define MXC_GPC_NEON		(MX51_GPC_BASE + 0x10)
+#define MXC_GPC_PGR_ARMPG_OFFSET	8
+#define MXC_GPC_PGR_ARMPG_MASK		(3 << 8)
+
+/* PGC */
+#define MXC_PGC_IPU_PGCR	(MXC_PGC_IPU_BASE + 0x0)
+#define MXC_PGC_IPU_PGSR	(MXC_PGC_IPU_BASE + 0xC)
+#define MXC_PGC_VPU_PGCR	(MXC_PGC_VPU_BASE + 0x0)
+#define MXC_PGC_VPU_PGSR	(MXC_PGC_VPU_BASE + 0xC)
+#define MXC_PGC_GPU_PGCR	(MXC_PGC_GPU_BASE + 0x0)
+#define MXC_PGC_GPU_PGSR	(MXC_PGC_GPU_BASE + 0xC)
+
+#define MXC_PGCR_PCR		1
+#define MXC_SRPGCR_PCR		1
+#define MXC_EMPGCR_PCR		1
+#define MXC_PGSR_PSR		1
+
+
+#define MXC_CORTEXA8_PLAT_LPC_DSM	(1 << 0)
+#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM	(1 << 1)
+
+/* SRPG */
+#define MXC_SRPG_NEON_SRPGCR	(MXC_SRPG_NEON_BASE + 0x0)
+#define MXC_SRPG_NEON_PUPSCR	(MXC_SRPG_NEON_BASE + 0x4)
+#define MXC_SRPG_NEON_PDNSCR	(MXC_SRPG_NEON_BASE + 0x8)
+
+#define MXC_SRPG_ARM_SRPGCR	(MXC_SRPG_ARM_BASE + 0x0)
+#define MXC_SRPG_ARM_PUPSCR	(MXC_SRPG_ARM_BASE + 0x4)
+#define MXC_SRPG_ARM_PDNSCR	(MXC_SRPG_ARM_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC0_SRPGCR	(MXC_SRPG_EMPGC0_BASE + 0x0)
+#define MXC_SRPG_EMPGC0_PUPSCR	(MXC_SRPG_EMPGC0_BASE + 0x4)
+#define MXC_SRPG_EMPGC0_PDNSCR	(MXC_SRPG_EMPGC0_BASE + 0x8)
+
+#define MXC_SRPG_EMPGC1_SRPGCR	(MXC_SRPG_EMPGC1_BASE + 0x0)
+#define MXC_SRPG_EMPGC1_PUPSCR	(MXC_SRPG_EMPGC1_BASE + 0x4)
+#define MXC_SRPG_EMPGC1_PDNSCR	(MXC_SRPG_EMPGC1_BASE + 0x8)
+
+#define MXC_SRPG_MEGAMIX_SRPGCR		(MXC_SRPG_MEGAMIX_BASE + 0x0)
+#define MXC_SRPG_MEGAMIX_PUPSCR		(MXC_SRPG_MEGAMIX_BASE + 0x4)
+#define MXC_SRPG_MEGAMIX_PDNSCR		(MXC_SRPG_MEGAMIX_BASE + 0x8)
+
+#define MXC_SRPGC_EMI_SRPGCR	(MXC_SRPGC_EMI_BASE + 0x0)
+#define MXC_SRPGC_EMI_PUPSCR	(MXC_SRPGC_EMI_BASE + 0x4)
+#define MXC_SRPGC_EMI_PDNSCR	(MXC_SRPGC_EMI_BASE + 0x8)
+
+#endif				/* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h
new file mode 100644
index 0000000..7216667
--- /dev/null
+++ b/arch/arm/mach-imx/devices-imx50.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
+#define imx50_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data;
+#define imx50_add_fec(pdata)	\
+	imx_add_fec(&imx50_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
+#define imx50_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-imx/devices-imx51.h b/arch/arm/mach-imx/devices-imx51.h
new file mode 100644
index 0000000..af488bc
--- /dev/null
+++ b/arch/arm/mach-imx/devices-imx51.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <mach/mx51.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx51_fec_data;
+#define imx51_add_fec(pdata)	\
+	imx_add_fec(&imx51_fec_data, pdata)
+
+extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
+#define imx51_add_fsl_usb2_udc(pdata)	\
+	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
+
+extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
+#define imx51_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
+#define imx51_add_hsi2c(pdata)	\
+	imx51_add_imx_i2c(2, pdata)
+
+extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
+#define imx51_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
+#define imx51_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
+
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
+#define imx51_add_mxc_ehci_otg(pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
+extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
+#define imx51_add_mxc_ehci_hs(id, pdata)	\
+	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
+
+extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
+#define imx51_add_mxc_nand(pdata)	\
+	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
+#define imx51_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx51_cspi_data;
+#define imx51_add_cspi(pdata)	\
+	imx_add_spi_imx(&imx51_cspi_data, pdata)
+
+extern const struct imx_spi_imx_data imx51_ecspi_data[];
+#define imx51_add_ecspi(id, pdata)	\
+	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
+#define imx51_add_imx2_wdt(id, pdata)	\
+	imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
+
+extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
+#define imx51_add_mxc_pwm(id)	\
+	imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
+
+extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
+#define imx51_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx51_pata_imx_data;
+#define imx51_add_pata_imx() \
+	imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-imx/devices-imx53.h b/arch/arm/mach-imx/devices-imx53.h
new file mode 100644
index 0000000..6e1e5d1
--- /dev/null
+++ b/arch/arm/mach-imx/devices-imx53.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@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 <mach/mx53.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_fec_data imx53_fec_data;
+#define imx53_add_fec(pdata)   \
+	imx_add_fec(&imx53_fec_data, pdata)
+
+extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
+#define imx53_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
+
+
+extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
+#define imx53_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
+
+extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
+#define imx53_add_sdhci_esdhc_imx(id, pdata)	\
+	imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
+
+extern const struct imx_spi_imx_data imx53_ecspi_data[];
+#define imx53_add_ecspi(id, pdata)	\
+	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
+#define imx53_add_imx2_wdt(id, pdata)	\
+	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
+
+extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
+#define imx53_add_imx_ssi(id, pdata)	\
+	imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
+
+extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
+#define imx53_add_imx_keypad(pdata)	\
+	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
+
+extern const struct imx_pata_imx_data imx53_pata_imx_data;
+#define imx53_add_pata_imx() \
+	imx_add_pata_imx(&imx53_pata_imx_data)
+
+extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-imx/efika.h b/arch/arm/mach-imx/efika.h
new file mode 100644
index 0000000..014aa98
--- /dev/null
+++ b/arch/arm/mach-imx/efika.h
@@ -0,0 +1,10 @@
+#ifndef _EFIKA_H
+#define _EFIKA_H
+
+#define EFIKA_WLAN_EN		IMX_GPIO_NR(2, 16)
+#define EFIKA_WLAN_RESET	IMX_GPIO_NR(2, 10)
+#define EFIKA_USB_PHY_RESET	IMX_GPIO_NR(2, 9)
+
+void __init efika_board_common_init(void);
+
+#endif
diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c
new file mode 100644
index 0000000..c17fa13
--- /dev/null
+++ b/arch/arm/mach-imx/ehci-imx5.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET			0
+#define MXC_H1_OFFSET			0x200
+#define MXC_H2_OFFSET			0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT		(1 << 5)	/* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
+
+#define MXC_USBCMD_OFFSET		0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+	void __iomem *usb_base;
+	void __iomem *usbotg_base;
+	void __iomem *usbother_base;
+	int ret = 0;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base) {
+		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	switch (port) {
+	case 0:	/* OTG port */
+		usbotg_base = usb_base + MXC_OTG_OFFSET;
+		break;
+	case 1:	/* Host 1 port */
+		usbotg_base = usb_base + MXC_H1_OFFSET;
+		break;
+	case 2: /* Host 2 port */
+		usbotg_base = usb_base + MXC_H2_OFFSET;
+		break;
+	default:
+		printk(KERN_ERR"%s no such port %d\n", __func__, port);
+		ret = -ENOENT;
+		goto error;
+	}
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	switch (port) {
+	case 0:	/*OTG port */
+		if (flags & MXC_EHCI_INTERNAL_PHY) {
+			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+				/* OC/USBPWR is not used */
+				v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			} else {
+				/* OC/USBPWR is used */
+				v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			}
+			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+			if (flags & MXC_EHCI_WAKEUP_ENABLED)
+				v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+			else
+				v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v |= MXC_OTG_UCTRL_OPM_BIT;
+			else
+				v &= ~MXC_OTG_UCTRL_OPM_BIT;
+			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+		}
+		break;
+	case 1:	/* Host 1 */
+		/*Host ULPI */
+		v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		else
+			v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+		v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+		else
+			v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+		__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+		v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+		if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+			/* Interrupt Threshold Control:Immediate (no threshold) */
+			v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+		__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+		break;
+	case 2: /* Host 2 ULPI */
+		v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		else
+			v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+		break;
+	}
+
+error:
+	iounmap(usb_base);
+	return ret;
+}
+
diff --git a/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c
new file mode 100644
index 0000000..a6a3ab8
--- /dev/null
+++ b/arch/arm/mach-imx/eukrea_mbimx51-baseboard.c
@@ -0,0 +1,206 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/leds.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/mach/arch.h>
+
+#include "devices-imx51.h"
+
+#define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
+#define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
+#define MBIMX51_LED1		IMX_GPIO_NR(3, 6)
+#define MBIMX51_LED2		IMX_GPIO_NR(3, 7)
+#define MBIMX51_LED3		IMX_GPIO_NR(3, 8)
+
+static const struct gpio_led mbimx51_leds[] __initconst = {
+	{
+		.name			= "led0",
+		.default_trigger	= "heartbeat",
+		.active_low		= 1,
+		.gpio			= MBIMX51_LED0,
+	},
+	{
+		.name			= "led1",
+		.default_trigger	= "nand-disk",
+		.active_low		= 1,
+		.gpio			= MBIMX51_LED1,
+	},
+	{
+		.name			= "led2",
+		.default_trigger	= "mmc0",
+		.active_low		= 1,
+		.gpio			= MBIMX51_LED2,
+	},
+	{
+		.name			= "led3",
+		.default_trigger	= "default-on",
+		.active_low		= 1,
+		.gpio			= MBIMX51_LED3,
+	},
+};
+
+static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
+	.leds		= mbimx51_leds,
+	.num_leds	= ARRAY_SIZE(mbimx51_leds),
+};
+
+static iomux_v3_cfg_t mbimx51_pads[] = {
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+
+	/* UART3 */
+	MX51_PAD_UART3_RXD__UART3_RXD,
+	MX51_PAD_UART3_TXD__UART3_TXD,
+	MX51_PAD_KEY_COL4__UART3_RTS,
+	MX51_PAD_KEY_COL5__UART3_CTS,
+
+	/* TSC2007 IRQ */
+	MX51_PAD_NANDF_D10__GPIO3_30,
+
+	/* LEDS */
+	MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
+	MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
+	MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
+	MX51_PAD_DISPB2_SER_RS__GPIO3_8,
+
+	/* KPP */
+	MX51_PAD_KEY_ROW0__KEY_ROW0,
+	MX51_PAD_KEY_ROW1__KEY_ROW1,
+	MX51_PAD_KEY_ROW2__KEY_ROW2,
+	MX51_PAD_KEY_ROW3__KEY_ROW3,
+	MX51_PAD_KEY_COL0__KEY_COL0,
+	MX51_PAD_KEY_COL1__KEY_COL1,
+	MX51_PAD_KEY_COL2__KEY_COL2,
+	MX51_PAD_KEY_COL3__KEY_COL3,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mbimx51_keymap[] = {
+	KEY(0, 0, KEY_1),
+	KEY(0, 1, KEY_2),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_UP),
+
+	KEY(1, 0, KEY_4),
+	KEY(1, 1, KEY_5),
+	KEY(1, 2, KEY_6),
+	KEY(1, 3, KEY_LEFT),
+
+	KEY(2, 0, KEY_7),
+	KEY(2, 1, KEY_8),
+	KEY(2, 2, KEY_9),
+	KEY(2, 3, KEY_RIGHT),
+
+	KEY(3, 0, KEY_0),
+	KEY(3, 1, KEY_DOWN),
+	KEY(3, 2, KEY_ESC),
+	KEY(3, 3, KEY_ENTER),
+};
+
+static const struct matrix_keymap_data mbimx51_map_data __initconst = {
+	.keymap		= mbimx51_keymap,
+	.keymap_size	= ARRAY_SIZE(mbimx51_keymap),
+};
+
+static int tsc2007_get_pendown_state(void)
+{
+	return !gpio_get_value(MBIMX51_TSC2007_GPIO);
+}
+
+struct tsc2007_platform_data tsc2007_data = {
+	.model = 2007,
+	.x_plate_ohms = 180,
+	.get_pendown_state = tsc2007_get_pendown_state,
+};
+
+static struct i2c_board_info mbimx51_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("tsc2007", 0x49),
+		.irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
+		.platform_data = &tsc2007_data,
+	}, {
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+};
+
+/*
+ * baseboard initialization.
+ */
+void __init eukrea_mbimx51_baseboard_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
+					ARRAY_SIZE(mbimx51_pads));
+
+	imx51_add_imx_uart(1, NULL);
+	imx51_add_imx_uart(2, &uart_pdata);
+
+	gpio_request(MBIMX51_LED0, "LED0");
+	gpio_direction_output(MBIMX51_LED0, 1);
+	gpio_free(MBIMX51_LED0);
+	gpio_request(MBIMX51_LED1, "LED1");
+	gpio_direction_output(MBIMX51_LED1, 1);
+	gpio_free(MBIMX51_LED1);
+	gpio_request(MBIMX51_LED2, "LED2");
+	gpio_direction_output(MBIMX51_LED2, 1);
+	gpio_free(MBIMX51_LED2);
+	gpio_request(MBIMX51_LED3, "LED3");
+	gpio_direction_output(MBIMX51_LED3, 1);
+	gpio_free(MBIMX51_LED3);
+
+	gpio_led_register_device(-1, &mbimx51_leds_info);
+
+	imx51_add_imx_keypad(&mbimx51_map_data);
+
+	gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
+	gpio_direction_input(MBIMX51_TSC2007_GPIO);
+	irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
+					IRQF_TRIGGER_FALLING);
+	i2c_register_board_info(1, mbimx51_i2c_devices,
+				ARRAY_SIZE(mbimx51_i2c_devices));
+
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+	imx51_add_sdhci_esdhc_imx(1, NULL);
+}
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
new file mode 100644
index 0000000..d817fc8
--- /dev/null
+++ b/arch/arm/mach-imx/eukrea_mbimxsd-baseboard.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2010 Eric Benard - eric@eukrea.com
+ *
+ * Based on pcm970-baseboard.c which is :
+ * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/audmux.h>
+
+#include "devices-imx51.h"
+
+static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
+	/* LED */
+	MX51_PAD_NANDF_D10__GPIO3_30,
+	/* SWITCH */
+	NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
+			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+	/* UART 3 */
+	MX51_PAD_UART3_RXD__UART3_RXD,
+	MX51_PAD_UART3_TXD__UART3_TXD,
+	MX51_PAD_KEY_COL4__UART3_RTS,
+	MX51_PAD_KEY_COL5__UART3_CTS,
+	/* SD */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+	/* SD1 CD */
+	NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
+			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+#define GPIO_LED1	IMX_GPIO_NR(3, 30)
+#define GPIO_SWITCH1	IMX_GPIO_NR(3, 31)
+
+static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
+	{
+		.name			= "led1",
+		.default_trigger	= "heartbeat",
+		.active_low		= 1,
+		.gpio			= GPIO_LED1,
+	},
+};
+
+static const struct gpio_led_platform_data
+		eukrea_mbimxsd_led_info __initconst = {
+	.leds		= eukrea_mbimxsd_leds,
+	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
+};
+
+static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
+	{
+		.gpio		= GPIO_SWITCH1,
+		.code		= BTN_0,
+		.desc		= "BP1",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+};
+
+static const struct gpio_keys_platform_data
+		eukrea_mbimxsd_button_data __initconst = {
+	.buttons	= eukrea_mbimxsd_gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1a),
+	},
+};
+
+/*
+ * system init for baseboard usage. Will be called by cpuimx51sd init.
+ *
+ * Add platform devices present on this baseboard and init
+ * them from CPU side as far as required to use them later on
+ */
+void __init eukrea_mbimxsd51_baseboard_init(void)
+{
+	if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
+			ARRAY_SIZE(eukrea_mbimxsd_pads)))
+		printk(KERN_ERR "error setting mbimxsd pads !\n");
+
+	imx51_add_imx_uart(1, NULL);
+	imx51_add_imx_uart(2, &uart_pdata);
+
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+
+	gpio_request(GPIO_LED1, "LED1");
+	gpio_direction_output(GPIO_LED1, 1);
+	gpio_free(GPIO_LED1);
+
+	gpio_request(GPIO_SWITCH1, "SWITCH1");
+	gpio_direction_input(GPIO_SWITCH1);
+	gpio_free(GPIO_SWITCH1);
+
+	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
+				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
+
+	gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
+	imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
+}
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
new file mode 100644
index 0000000..e6bad17
--- /dev/null
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx51.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx51_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx51_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx51_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx51_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx51_irq_match);
+
+	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx51_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx51_auxdata_lookup, NULL);
+}
+
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init_dt();
+}
+
+static struct sys_timer imx51_timer = {
+	.init = imx51_timer_init,
+};
+
+static const char *imx51_dt_board_compat[] __initdata = {
+	"fsl,imx51-babbage",
+	NULL
+};
+
+DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
+	.map_io		= mx51_map_io,
+	.init_early	= imx51_init_early,
+	.init_irq	= mx51_init_irq,
+	.handle_irq	= imx51_handle_irq,
+	.timer		= &imx51_timer,
+	.init_machine	= imx51_dt_init,
+	.dt_compat	= imx51_dt_board_compat,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
new file mode 100644
index 0000000..05ebb3e
--- /dev/null
+++ b/arch/arm/mach-imx/imx53-dt.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * 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/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static int __init imx53_tzic_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	irq_domain_add_simple(np, 0);
+	return 0;
+}
+
+static int __init imx53_gpio_add_irq_domain(struct device_node *np,
+				struct device_node *interrupt_parent)
+{
+	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
+
+	gpio_irq_base -= 32;
+	irq_domain_add_simple(np, gpio_irq_base);
+
+	return 0;
+}
+
+static const struct of_device_id imx53_irq_match[] __initconst = {
+	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
+	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
+	{ /* sentinel */ }
+};
+
+static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
+	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
+	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
+	{ /* sentinel */ }
+};
+
+static void __init imx53_dt_init(void)
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	void (*func)(void);
+
+	of_irq_init(imx53_irq_match);
+
+	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
+	if (node) {
+		of_id = of_match_node(imx53_iomuxc_of_match, node);
+		func = of_id->data;
+		func();
+		of_node_put(node);
+	}
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+	.init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+	"fsl,imx53-ard",
+	"fsl,imx53-evk",
+	"fsl,imx53-qsb",
+	"fsl,imx53-smd",
+	NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+	.map_io		= mx53_map_io,
+	.init_early	= imx53_init_early,
+	.init_irq	= mx53_init_irq,
+	.handle_irq	= imx53_handle_irq,
+	.timer		= &imx53_timer,
+	.init_machine	= imx53_dt_init,
+	.dt_compat	= imx53_dt_board_compat,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51.c b/arch/arm/mach-imx/mach-cpuimx51.c
new file mode 100644
index 0000000..944025d
--- /dev/null
+++ b/arch/arm/mach-imx/mach-cpuimx51.c
@@ -0,0 +1,301 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+
+#define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
+#define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
+#define CPUIMX51_QUARTB_GPIO	IMX_GPIO_NR(3, 25)
+#define CPUIMX51_QUARTC_GPIO	IMX_GPIO_NR(3, 26)
+#define CPUIMX51_QUARTD_GPIO	IMX_GPIO_NR(3, 27)
+#define CPUIMX51_QUART_XTAL	14745600
+#define CPUIMX51_QUART_REGSHIFT	17
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET		0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)
+
+#define	MX51_USB_PLLDIV_12_MHZ		0x00
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+#define	MX51_USB_PLL_DIV_24_MHZ		0x02
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
+		.irqflags = IRQF_TRIGGER_HIGH,
+		.uartclk = CPUIMX51_QUART_XTAL,
+		.regshift = CPUIMX51_QUART_REGSHIFT,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
+		.irqflags = IRQF_TRIGGER_HIGH,
+		.uartclk = CPUIMX51_QUART_XTAL,
+		.regshift = CPUIMX51_QUART_REGSHIFT,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
+		.irqflags = IRQF_TRIGGER_HIGH,
+		.uartclk = CPUIMX51_QUART_XTAL,
+		.regshift = CPUIMX51_QUART_REGSHIFT,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
+		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
+		.irqflags = IRQF_TRIGGER_HIGH,
+		.uartclk = CPUIMX51_QUART_XTAL,
+		.regshift = CPUIMX51_QUART_REGSHIFT,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
+	}, {
+	}
+};
+
+static struct platform_device serial_device = {
+	.name = "serial8250",
+	.id = 0,
+	.dev = {
+		.platform_data = serial_platform_data,
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&serial_device,
+};
+
+static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* I2C2 */
+	MX51_PAD_GPIO1_2__I2C2_SCL,
+	MX51_PAD_GPIO1_3__I2C2_SDA,
+	MX51_PAD_NANDF_D10__GPIO3_30,
+
+	/* QUART IRQ */
+	MX51_PAD_NANDF_D15__GPIO3_25,
+	MX51_PAD_NANDF_D14__GPIO3_26,
+	MX51_PAD_NANDF_D13__GPIO3_27,
+	MX51_PAD_NANDF_D12__GPIO3_28,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+	MX51_PAD_USBH1_STP__USBH1_STP,
+};
+
+static const struct mxc_nand_platform_data
+		eukrea_cpuimx51_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const
+struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
+	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+	.init		= initialize_otg_port,
+	.portsc	= MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+	.init		= initialize_usbh1_port,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
+
+/*
+ * Board specific initialization.
+ */
+static void __init eukrea_cpuimx51_init(void)
+{
+	imx51_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
+					ARRAY_SIZE(eukrea_cpuimx51_pads));
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
+
+	gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
+	gpio_direction_input(CPUIMX51_QUARTA_GPIO);
+	gpio_free(CPUIMX51_QUARTA_GPIO);
+	gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
+	gpio_direction_input(CPUIMX51_QUARTB_GPIO);
+	gpio_free(CPUIMX51_QUARTB_GPIO);
+	gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
+	gpio_direction_input(CPUIMX51_QUARTC_GPIO);
+	gpio_free(CPUIMX51_QUARTC_GPIO);
+	gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
+	gpio_direction_input(CPUIMX51_QUARTD_GPIO);
+	gpio_free(CPUIMX51_QUARTD_GPIO);
+
+	imx51_add_fec(NULL);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
+	i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
+				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
+
+	if (otg_mode_host)
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
+	else {
+		initialize_otg_port(NULL);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
+	}
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
+	eukrea_mbimx51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+	.init	= eukrea_cpuimx51_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
+	/* Maintainer: Eric Bénard <eric@eukrea.com> */
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
new file mode 100644
index 0000000..9fbe923
--- /dev/null
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -0,0 +1,339 @@
+/*
+ *
+ * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
+ *
+ * based on board-mx51_babbage.c which is
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/i2c/tsc2007.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/can/platform/mcp251x.h>
+
+#include <mach/eukrea-baseboards.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define USBH1_RST		IMX_GPIO_NR(2, 28)
+#define ETH_RST			IMX_GPIO_NR(2, 31)
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 12)
+#define CAN_IRQGPIO		IMX_GPIO_NR(1, 1)
+#define CAN_RST			IMX_GPIO_NR(4, 15)
+#define CAN_NCS			IMX_GPIO_NR(4, 24)
+#define CAN_RXOBF		IMX_GPIO_NR(1, 4)
+#define CAN_RX1BF		IMX_GPIO_NR(1, 6)
+#define CAN_TXORTS		IMX_GPIO_NR(1, 7)
+#define CAN_TX1RTS		IMX_GPIO_NR(1, 8)
+#define CAN_TX2RTS		IMX_GPIO_NR(1, 9)
+#define I2C_SCL			IMX_GPIO_NR(4, 16)
+#define I2C_SDA			IMX_GPIO_NR(4, 17)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET		0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)
+
+#define	MX51_USB_PLLDIV_12_MHZ		0x00
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+#define	MX51_USB_PLL_DIV_24_MHZ		0x02
+
+static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+	MX51_PAD_USBH1_STP__USBH1_STP,
+	MX51_PAD_EIM_CS3__GPIO2_28,		/* PHY nRESET */
+
+	/* FEC */
+	MX51_PAD_EIM_DTACK__GPIO2_31,		/* PHY nRESET */
+
+	/* HSI2C */
+	MX51_PAD_I2C1_CLK__GPIO4_16,
+	MX51_PAD_I2C1_DAT__GPIO4_17,
+
+	/* CAN */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,		/* nCS */
+	MX51_PAD_CSI2_PIXCLK__GPIO4_15,		/* nReset */
+	MX51_PAD_GPIO1_1__GPIO1_1,		/* IRQ */
+	MX51_PAD_GPIO1_4__GPIO1_4,		/* Control signals */
+	MX51_PAD_GPIO1_6__GPIO1_6,
+	MX51_PAD_GPIO1_7__GPIO1_7,
+	MX51_PAD_GPIO1_8__GPIO1_8,
+	MX51_PAD_GPIO1_9__GPIO1_9,
+
+	/* Touchscreen */
+	/* IRQ */
+	NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
+			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
+};
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static struct tsc2007_platform_data tsc2007_info = {
+	.model			= 2007,
+	.x_plate_ohms		= 180,
+};
+
+static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	}, {
+		I2C_BOARD_INFO("tsc2007", 0x49),
+		.type		= "tsc2007",
+		.platform_data	= &tsc2007_info,
+		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
+	},
+};
+
+static const struct mxc_nand_platform_data
+		eukrea_cpuimx51sd_nand_board_info __initconst = {
+	.width		= 1,
+	.hw_ecc		= 1,
+	.flash_bbt	= 1,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* The clock for the USBH1 ULPI port will come from the PHY. */
+	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+			usbother_base + MX51_USB_CTRL_1_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+	.init		= initialize_otg_port,
+	.portsc	= MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+	.init		= initialize_usbh1_port,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init eukrea_cpuimx51sd_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
+
+static struct i2c_gpio_platform_data pdata = {
+	.sda_pin		= I2C_SDA,
+	.sda_is_open_drain	= 0,
+	.scl_pin		= I2C_SCL,
+	.scl_is_open_drain	= 0,
+	.udelay			= 2,
+};
+
+static struct platform_device hsi2c_gpio_device = {
+	.name			= "i2c-gpio",
+	.id			= 0,
+	.dev.platform_data	= &pdata,
+};
+
+static struct mcp251x_platform_data mcp251x_info = {
+	.oscillator_frequency = 24E6,
+};
+
+static struct spi_board_info cpuimx51sd_spi_device[] = {
+	{
+		.modalias        = "mcp2515",
+		.max_speed_hz    = 10000000,
+		.bus_num         = 0,
+		.mode		= SPI_MODE_0,
+		.chip_select     = 0,
+		.platform_data   = &mcp251x_info,
+		.irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
+	},
+};
+
+static int cpuimx51sd_spi1_cs[] = {
+	CAN_NCS,
+};
+
+static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
+	.chipselect	= cpuimx51sd_spi1_cs,
+	.num_chipselect	= ARRAY_SIZE(cpuimx51sd_spi1_cs),
+};
+
+static struct platform_device *platform_devices[] __initdata = {
+	&hsi2c_gpio_device,
+};
+
+static void __init eukrea_cpuimx51sd_init(void)
+{
+	imx51_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
+					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
+
+	gpio_request(ETH_RST, "eth_rst");
+	gpio_set_value(ETH_RST, 1);
+	imx51_add_fec(NULL);
+
+	gpio_request(CAN_IRQGPIO, "can_irq");
+	gpio_direction_input(CAN_IRQGPIO);
+	gpio_free(CAN_IRQGPIO);
+	gpio_request(CAN_NCS, "can_ncs");
+	gpio_direction_output(CAN_NCS, 1);
+	gpio_free(CAN_NCS);
+	gpio_request(CAN_RST, "can_rst");
+	gpio_direction_output(CAN_RST, 0);
+	msleep(20);
+	gpio_set_value(CAN_RST, 1);
+	imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+	spi_register_board_info(cpuimx51sd_spi_device,
+				ARRAY_SIZE(cpuimx51sd_spi_device));
+
+	gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
+	gpio_direction_input(TSC2007_IRQGPIO);
+	gpio_free(TSC2007_IRQGPIO);
+
+	i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
+			ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
+	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+	if (otg_mode_host)
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
+	else {
+		initialize_otg_port(NULL);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
+	}
+
+	gpio_request(USBH1_RST, "usb_rst");
+	gpio_direction_output(USBH1_RST, 0);
+	msleep(20);
+	gpio_set_value(USBH1_RST, 1);
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
+
+#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
+	eukrea_mbimxsd51_baseboard_init();
+#endif
+}
+
+static void __init eukrea_cpuimx51sd_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mxc_timer = {
+	.init	= eukrea_cpuimx51sd_timer_init,
+};
+
+MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
+	/* Maintainer: Eric Bénard <eric@eukrea.com> */
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51sd_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c
new file mode 100644
index 0000000..42b66e8
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx50_rdp.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx50.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx50.h"
+
+#define FEC_EN		IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B	IMX_GPIO_NR(4, 12)
+
+static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
+	/* SD1 */
+	MX50_PAD_ECSPI2_SS0__GPIO_4_19,
+	MX50_PAD_EIM_CRE__GPIO_1_27,
+	MX50_PAD_SD1_CMD__SD1_CMD,
+
+	MX50_PAD_SD1_CLK__SD1_CLK,
+	MX50_PAD_SD1_D0__SD1_D0,
+	MX50_PAD_SD1_D1__SD1_D1,
+	MX50_PAD_SD1_D2__SD1_D2,
+	MX50_PAD_SD1_D3__SD1_D3,
+
+	/* SD2 */
+	MX50_PAD_SD2_CD__GPIO_5_17,
+	MX50_PAD_SD2_WP__GPIO_5_16,
+	MX50_PAD_SD2_CMD__SD2_CMD,
+	MX50_PAD_SD2_CLK__SD2_CLK,
+	MX50_PAD_SD2_D0__SD2_D0,
+	MX50_PAD_SD2_D1__SD2_D1,
+	MX50_PAD_SD2_D2__SD2_D2,
+	MX50_PAD_SD2_D3__SD2_D3,
+	MX50_PAD_SD2_D4__SD2_D4,
+	MX50_PAD_SD2_D5__SD2_D5,
+	MX50_PAD_SD2_D6__SD2_D6,
+	MX50_PAD_SD2_D7__SD2_D7,
+
+	/* SD3 */
+	MX50_PAD_SD3_CMD__SD3_CMD,
+	MX50_PAD_SD3_CLK__SD3_CLK,
+	MX50_PAD_SD3_D0__SD3_D0,
+	MX50_PAD_SD3_D1__SD3_D1,
+	MX50_PAD_SD3_D2__SD3_D2,
+	MX50_PAD_SD3_D3__SD3_D3,
+	MX50_PAD_SD3_D4__SD3_D4,
+	MX50_PAD_SD3_D5__SD3_D5,
+	MX50_PAD_SD3_D6__SD3_D6,
+	MX50_PAD_SD3_D7__SD3_D7,
+
+	/* PWR_INT */
+	MX50_PAD_ECSPI2_MISO__GPIO_4_18,
+
+	/* UART pad setting */
+	MX50_PAD_UART1_TXD__UART1_TXD,
+	MX50_PAD_UART1_RXD__UART1_RXD,
+	MX50_PAD_UART1_RTS__UART1_RTS,
+	MX50_PAD_UART2_TXD__UART2_TXD,
+	MX50_PAD_UART2_RXD__UART2_RXD,
+	MX50_PAD_UART2_CTS__UART2_CTS,
+	MX50_PAD_UART2_RTS__UART2_RTS,
+
+	MX50_PAD_I2C1_SCL__I2C1_SCL,
+	MX50_PAD_I2C1_SDA__I2C1_SDA,
+	MX50_PAD_I2C2_SCL__I2C2_SCL,
+	MX50_PAD_I2C2_SDA__I2C2_SDA,
+
+	MX50_PAD_EPITO__USBH1_PWR,
+	/* Need to comment below line if
+	 * one needs to debug owire.
+	 */
+	MX50_PAD_OWIRE__USBH1_OC,
+	/* using gpio to control otg pwr */
+	MX50_PAD_PWM2__GPIO_6_25,
+	MX50_PAD_I2C3_SCL__USBOTG_OC,
+
+	MX50_PAD_SSI_RXC__FEC_MDIO,
+	MX50_PAD_SSI_RXFS__FEC_MDC,
+	MX50_PAD_DISP_D0__FEC_TXCLK,
+	MX50_PAD_DISP_D1__FEC_RX_ER,
+	MX50_PAD_DISP_D2__FEC_RX_DV,
+	MX50_PAD_DISP_D3__FEC_RXD1,
+	MX50_PAD_DISP_D4__FEC_RXD0,
+	MX50_PAD_DISP_D5__FEC_TX_EN,
+	MX50_PAD_DISP_D6__FEC_TXD1,
+	MX50_PAD_DISP_D7__FEC_TXD0,
+	MX50_PAD_I2C3_SDA__GPIO_6_23,
+	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
+
+	MX50_PAD_CSPI_SS0__CSPI_SS0,
+	MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
+	MX50_PAD_CSPI_MOSI__CSPI_MOSI,
+	MX50_PAD_CSPI_MISO__CSPI_MISO,
+
+	/* SGTL500_OSC_EN */
+	MX50_PAD_UART1_CTS__GPIO_6_8,
+
+	/* SGTL_AMP_SHDN */
+	MX50_PAD_UART3_RXD__GPIO_6_15,
+
+	/* Keypad */
+	MX50_PAD_KEY_COL0__KEY_COL0,
+	MX50_PAD_KEY_ROW0__KEY_ROW0,
+	MX50_PAD_KEY_COL1__KEY_COL1,
+	MX50_PAD_KEY_ROW1__KEY_ROW1,
+	MX50_PAD_KEY_COL2__KEY_COL2,
+	MX50_PAD_KEY_ROW2__KEY_ROW2,
+	MX50_PAD_KEY_COL3__KEY_COL3,
+	MX50_PAD_KEY_ROW3__KEY_ROW3,
+	MX50_PAD_EIM_DA0__KEY_COL4,
+	MX50_PAD_EIM_DA1__KEY_ROW4,
+	MX50_PAD_EIM_DA2__KEY_COL5,
+	MX50_PAD_EIM_DA3__KEY_ROW5,
+	MX50_PAD_EIM_DA4__KEY_COL6,
+	MX50_PAD_EIM_DA5__KEY_ROW6,
+	MX50_PAD_EIM_DA6__KEY_COL7,
+	MX50_PAD_EIM_DA7__KEY_ROW7,
+	/*EIM pads */
+	MX50_PAD_EIM_DA8__GPIO_1_8,
+	MX50_PAD_EIM_DA9__GPIO_1_9,
+	MX50_PAD_EIM_DA10__GPIO_1_10,
+	MX50_PAD_EIM_DA11__GPIO_1_11,
+	MX50_PAD_EIM_DA12__GPIO_1_12,
+	MX50_PAD_EIM_DA13__GPIO_1_13,
+	MX50_PAD_EIM_DA14__GPIO_1_14,
+	MX50_PAD_EIM_DA15__GPIO_1_15,
+	MX50_PAD_EIM_CS2__GPIO_1_16,
+	MX50_PAD_EIM_CS1__GPIO_1_17,
+	MX50_PAD_EIM_CS0__GPIO_1_18,
+	MX50_PAD_EIM_EB0__GPIO_1_19,
+	MX50_PAD_EIM_EB1__GPIO_1_20,
+	MX50_PAD_EIM_WAIT__GPIO_1_21,
+	MX50_PAD_EIM_BCLK__GPIO_1_22,
+	MX50_PAD_EIM_RDY__GPIO_1_23,
+	MX50_PAD_EIM_OE__GPIO_1_24,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct fec_platform_data fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+	gpio_request(FEC_EN, "fec-en");
+	gpio_direction_output(FEC_EN, 0);
+	gpio_request(FEC_RESET_B, "fec-reset_b");
+	gpio_direction_output(FEC_RESET_B, 0);
+	msleep(1);
+	gpio_set_value(FEC_RESET_B, 1);
+}
+
+static const struct imxi2c_platform_data i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx50_rdp_board_init(void)
+{
+	imx50_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
+					ARRAY_SIZE(mx50_rdp_pads));
+
+	imx50_add_imx_uart(0, &uart_pdata);
+	imx50_add_imx_uart(1, &uart_pdata);
+	mx50_rdp_fec_reset();
+	imx50_add_fec(&fec_data);
+	imx50_add_imx_i2c(0, &i2c_data);
+	imx50_add_imx_i2c(1, &i2c_data);
+	imx50_add_imx_i2c(2, &i2c_data);
+}
+
+static void __init mx50_rdp_timer_init(void)
+{
+	mx50_clocks_init(32768, 24000000, 22579200);
+}
+
+static struct sys_timer mx50_rdp_timer = {
+	.init	= mx50_rdp_timer_init,
+};
+
+MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
+	.map_io = mx50_map_io,
+	.init_early = imx50_init_early,
+	.init_irq = mx50_init_irq,
+	.handle_irq = imx50_handle_irq,
+	.timer = &mx50_rdp_timer,
+	.init_machine = mx50_rdp_board_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c
new file mode 100644
index 0000000..83eab41
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx51_3ds.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx51.h>
+#include <mach/3ds_debugboard.h>
+
+#include "devices-imx51.h"
+
+#define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
+#define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
+
+static iomux_v3_cfg_t mx51_3ds_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+	MX51_PAD_EIM_D25__UART2_CTS,
+	MX51_PAD_EIM_D26__UART2_RTS,
+
+	/* UART3 */
+	MX51_PAD_UART3_RXD__UART3_RXD,
+	MX51_PAD_UART3_TXD__UART3_TXD,
+	MX51_PAD_EIM_D24__UART3_CTS,
+	MX51_PAD_EIM_D27__UART3_RTS,
+
+	/* CPLD PARENT IRQ PIN */
+	MX51_PAD_GPIO1_6__GPIO1_6,
+
+	/* KPP */
+	MX51_PAD_KEY_ROW0__KEY_ROW0,
+	MX51_PAD_KEY_ROW1__KEY_ROW1,
+	MX51_PAD_KEY_ROW2__KEY_ROW2,
+	MX51_PAD_KEY_ROW3__KEY_ROW3,
+	MX51_PAD_KEY_COL0__KEY_COL0,
+	MX51_PAD_KEY_COL1__KEY_COL1,
+	MX51_PAD_KEY_COL2__KEY_COL2,
+	MX51_PAD_KEY_COL3__KEY_COL3,
+	MX51_PAD_KEY_COL4__KEY_COL4,
+	MX51_PAD_KEY_COL5__KEY_COL5,
+
+	/* eCSPI2 */
+	MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
+	MX51_PAD_NANDF_RB3__ECSPI2_MISO,
+	MX51_PAD_NANDF_D15__ECSPI2_MOSI,
+	MX51_PAD_NANDF_D12__GPIO3_28,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static int mx51_3ds_board_keymap[] = {
+	KEY(0, 0, KEY_1),
+	KEY(0, 1, KEY_2),
+	KEY(0, 2, KEY_3),
+	KEY(0, 3, KEY_F1),
+	KEY(0, 4, KEY_UP),
+	KEY(0, 5, KEY_F2),
+
+	KEY(1, 0, KEY_4),
+	KEY(1, 1, KEY_5),
+	KEY(1, 2, KEY_6),
+	KEY(1, 3, KEY_LEFT),
+	KEY(1, 4, KEY_SELECT),
+	KEY(1, 5, KEY_RIGHT),
+
+	KEY(2, 0, KEY_7),
+	KEY(2, 1, KEY_8),
+	KEY(2, 2, KEY_9),
+	KEY(2, 3, KEY_F3),
+	KEY(2, 4, KEY_DOWN),
+	KEY(2, 5, KEY_F4),
+
+	KEY(3, 0, KEY_0),
+	KEY(3, 1, KEY_OK),
+	KEY(3, 2, KEY_ESC),
+	KEY(3, 3, KEY_ENTER),
+	KEY(3, 4, KEY_MENU),
+	KEY(3, 5, KEY_BACK)
+};
+
+static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
+	.keymap		= mx51_3ds_board_keymap,
+	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
+};
+
+static int mx51_3ds_spi2_cs[] = {
+	MXC_SPI_CS(0),
+	MX51_3DS_ECSPI2_CS,
+};
+
+static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
+	.chipselect	= mx51_3ds_spi2_cs,
+	.num_chipselect	= ARRAY_SIZE(mx51_3ds_spi2_cs),
+};
+
+static struct spi_board_info mx51_3ds_spi_nor_device[] = {
+	{
+	 .modalias = "m25p80",
+	 .max_speed_hz = 25000000,	/* max spi clock (SCK) speed in HZ */
+	 .bus_num = 1,
+	 .chip_select = 1,
+	 .mode = SPI_MODE_0,
+	 .platform_data = NULL,},
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_3ds_init(void)
+{
+	imx51_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
+					ARRAY_SIZE(mx51_3ds_pads));
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, &uart_pdata);
+	imx51_add_imx_uart(2, &uart_pdata);
+
+	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
+	spi_register_board_info(mx51_3ds_spi_nor_device,
+				ARRAY_SIZE(mx51_3ds_spi_nor_device));
+
+	if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+		printk(KERN_WARNING "Init of the debugboard failed, all "
+				    "devices on the board are unusable.\n");
+
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+	imx51_add_imx_keypad(&mx51_3ds_map_data);
+	imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_3ds_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_3ds_timer = {
+	.init = mx51_3ds_timer_init,
+};
+
+MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
+	/* Maintainer: Freescale Semiconductor, Inc. */
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.timer = &mx51_3ds_timer,
+	.init_machine = mx51_3ds_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
new file mode 100644
index 0000000..e4b822e
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx51_babbage.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "cpu_op-mx51.h"
+
+#define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
+#define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
+#define BABBAGE_USB_PHY_RESET	IMX_GPIO_NR(2, 5)
+#define BABBAGE_FEC_PHY_RESET	IMX_GPIO_NR(2, 14)
+#define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
+#define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
+#define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
+#define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
+#define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
+
+/* USB_CTRL_1 */
+#define MX51_USB_CTRL_1_OFFSET			0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN		(1 << 25)
+
+#define	MX51_USB_PLLDIV_12_MHZ		0x00
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+#define	MX51_USB_PLL_DIV_24_MHZ	0x02
+
+static struct gpio_keys_button babbage_buttons[] = {
+	{
+		.gpio		= BABBAGE_POWER_KEY,
+		.code		= BTN_0,
+		.desc		= "PWR",
+		.active_low	= 1,
+		.wakeup		= 1,
+	},
+};
+
+static const struct gpio_keys_platform_data imx_button_data __initconst = {
+	.buttons	= babbage_buttons,
+	.nbuttons	= ARRAY_SIZE(babbage_buttons),
+};
+
+static iomux_v3_cfg_t mx51babbage_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* UART2 */
+	MX51_PAD_UART2_RXD__UART2_RXD,
+	MX51_PAD_UART2_TXD__UART2_TXD,
+
+	/* UART3 */
+	MX51_PAD_EIM_D25__UART3_RXD,
+	MX51_PAD_EIM_D26__UART3_TXD,
+	MX51_PAD_EIM_D27__UART3_RTS,
+	MX51_PAD_EIM_D24__UART3_CTS,
+
+	/* I2C1 */
+	MX51_PAD_EIM_D16__I2C1_SDA,
+	MX51_PAD_EIM_D19__I2C1_SCL,
+
+	/* I2C2 */
+	MX51_PAD_KEY_COL4__I2C2_SCL,
+	MX51_PAD_KEY_COL5__I2C2_SDA,
+
+	/* HSI2C */
+	MX51_PAD_I2C1_CLK__I2C1_CLK,
+	MX51_PAD_I2C1_DAT__I2C1_DAT,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+	/* USB HUB reset line*/
+	MX51_PAD_GPIO1_7__GPIO1_7,
+
+	/* USB PHY reset line */
+	MX51_PAD_EIM_D21__GPIO2_5,
+
+	/* FEC */
+	MX51_PAD_EIM_EB2__FEC_MDIO,
+	MX51_PAD_EIM_EB3__FEC_RDATA1,
+	MX51_PAD_EIM_CS2__FEC_RDATA2,
+	MX51_PAD_EIM_CS3__FEC_RDATA3,
+	MX51_PAD_EIM_CS4__FEC_RX_ER,
+	MX51_PAD_EIM_CS5__FEC_CRS,
+	MX51_PAD_NANDF_RB2__FEC_COL,
+	MX51_PAD_NANDF_RB3__FEC_RX_CLK,
+	MX51_PAD_NANDF_D9__FEC_RDATA0,
+	MX51_PAD_NANDF_D8__FEC_TDATA0,
+	MX51_PAD_NANDF_CS2__FEC_TX_ER,
+	MX51_PAD_NANDF_CS3__FEC_MDC,
+	MX51_PAD_NANDF_CS4__FEC_TDATA1,
+	MX51_PAD_NANDF_CS5__FEC_TDATA2,
+	MX51_PAD_NANDF_CS6__FEC_TDATA3,
+	MX51_PAD_NANDF_CS7__FEC_TX_EN,
+	MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
+
+	/* FEC PHY reset line */
+	MX51_PAD_EIM_A20__GPIO2_14,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+	/* CD/WP from controller */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+	/* CD/WP gpio */
+	MX51_PAD_GPIO1_6__GPIO1_6,
+	MX51_PAD_GPIO1_5__GPIO1_5,
+
+	/* eCSPI1 */
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
+	.bitrate = 400000,
+};
+
+static struct gpio mx51_babbage_usbh1_gpios[] = {
+	{ BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
+	{ BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
+};
+
+static int gpio_usbh1_active(void)
+{
+	iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+	int ret;
+
+	/* Set USBH1_STP to GPIO and toggle it */
+	mxc_iomux_v3_setup_pad(usbh1stp_gpio);
+	ret = gpio_request_array(mx51_babbage_usbh1_gpios,
+					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+
+	if (ret) {
+		pr_debug("failed to get USBH1 pins: %d\n", ret);
+		return ret;
+	}
+
+	msleep(100);
+	gpio_set_value(BABBAGE_USBH1_STP, 1);
+	gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
+	gpio_free_array(mx51_babbage_usbh1_gpios,
+					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
+	return 0;
+}
+
+static inline void babbage_usbhub_reset(void)
+{
+	int ret;
+
+	/* Reset USB hub */
+	ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
+					GPIOF_OUT_INIT_LOW, "GPIO1_7");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
+		return;
+	}
+
+	msleep(2);
+	/* Deassert reset */
+	gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
+}
+
+static inline void babbage_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
+					GPIOF_OUT_INIT_LOW, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	msleep(1);
+	gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
+}
+
+/* This function is board specific as the bit mask for the plldiv will also
+be different for other Freescale SoCs, thus a common bitmask is not
+possible and cannot get place in /plat-mxc/ehci.c.*/
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
+}
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
+	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+	.init		= initialize_otg_port,
+	.portsc	= MXC_EHCI_UTMI_16BIT,
+};
+
+static const struct fsl_usb2_platform_data usb_pdata __initconst = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+};
+
+static const struct mxc_usbh_platform_data usbh1_config __initconst = {
+	.init		= initialize_usbh1_port,
+	.portsc	= MXC_EHCI_MODE_ULPI,
+};
+
+static int otg_mode_host;
+
+static int __init babbage_otg_mode(char *options)
+{
+	if (!strcmp(options, "host"))
+		otg_mode_host = 1;
+	else if (!strcmp(options, "device"))
+		otg_mode_host = 0;
+	else
+		pr_info("otg_mode neither \"host\" nor \"device\". "
+			"Defaulting to device\n");
+	return 0;
+}
+__setup("otg_mode=", babbage_otg_mode);
+
+static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
+	{
+		.modalias = "mtd_dataflash",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_0,
+		.platform_data = NULL,
+	},
+};
+
+static int mx51_babbage_spi_cs[] = {
+	BABBAGE_ECSPI1_CS0,
+	BABBAGE_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
+	.chipselect     = mx51_babbage_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
+	.cd_gpio = BABBAGE_SD2_CD,
+	.wp_gpio = BABBAGE_SD2_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
+};
+
+void __init imx51_babbage_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
+					 ARRAY_SIZE(mx51babbage_pads));
+}
+
+/*
+ * Board specific initialization.
+ */
+static void __init mx51_babbage_init(void)
+{
+	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
+		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
+
+	imx51_soc_init();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+	imx51_babbage_common_init();
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, NULL);
+	imx51_add_imx_uart(2, &uart_pdata);
+
+	babbage_fec_reset();
+	imx51_add_fec(NULL);
+
+	/* Set the PAD settings for the pwr key. */
+	mxc_iomux_v3_setup_pad(power_key);
+	imx_add_gpio_keys(&imx_button_data);
+
+	imx51_add_imx_i2c(0, &babbage_i2c_data);
+	imx51_add_imx_i2c(1, &babbage_i2c_data);
+	imx51_add_hsi2c(&babbage_hsi2c_data);
+
+	if (otg_mode_host)
+		imx51_add_mxc_ehci_otg(&dr_utmi_config);
+	else {
+		initialize_otg_port(NULL);
+		imx51_add_fsl_usb2_udc(&usb_pdata);
+	}
+
+	gpio_usbh1_active();
+	imx51_add_mxc_ehci_hs(1, &usbh1_config);
+	/* setback USBH1_STP to be function */
+	mxc_iomux_v3_setup_pad(usbh1stp);
+	babbage_usbhub_reset();
+
+	imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
+	imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
+
+	spi_register_board_info(mx51_babbage_spi_board_info,
+		ARRAY_SIZE(mx51_babbage_spi_board_info));
+	imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
+	imx51_add_imx2_wdt(0, NULL);
+}
+
+static void __init mx51_babbage_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx51_babbage_timer = {
+	.init = mx51_babbage_timer_init,
+};
+
+MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
+	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.timer = &mx51_babbage_timer,
+	.init_machine = mx51_babbage_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_efikamx.c b/arch/arm/mach-imx/mach-mx51_efikamx.c
new file mode 100644
index 0000000..3a5ed2d
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx51_efikamx.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2010 Linaro Limited
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
+#define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
+#define EFIKAMX_PCBID2		IMX_GPIO_NR(3, 11)
+
+#define EFIKAMX_BLUE_LED	IMX_GPIO_NR(3, 13)
+#define EFIKAMX_GREEN_LED	IMX_GPIO_NR(3, 14)
+#define EFIKAMX_RED_LED		IMX_GPIO_NR(3, 15)
+
+#define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
+
+/* board 1.1 doesn't have same reset gpio */
+#define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
+#define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
+
+#define EFIKAMX_POWEROFF	IMX_GPIO_NR(4, 13)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
+/* the pci ids pin have pull up. they're driven low according to board id */
+#define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PCBID2	IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
+#define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikamx_pads[] = {
+	/* board id */
+	MX51_PAD_PCBID0,
+	MX51_PAD_PCBID1,
+	MX51_PAD_PCBID2,
+
+	/* leds */
+	MX51_PAD_CSI1_D9__GPIO3_13,
+	MX51_PAD_CSI1_VSYNC__GPIO3_14,
+	MX51_PAD_CSI1_HSYNC__GPIO3_15,
+
+	/* power key */
+	MX51_PAD_PWRKEY,
+
+	/* reset */
+	MX51_PAD_DI1_PIN13__GPIO3_2,
+	MX51_PAD_GPIO1_4__GPIO1_4,
+
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
+};
+
+/*   PCBID2  PCBID1 PCBID0  STATE
+	1       1      1    ER1:rev1.1
+	1       1      0    ER2:rev1.2
+	1       0      1    ER3:rev1.3
+	1       0      0    ER4:rev1.4
+*/
+static void __init mx51_efikamx_board_id(void)
+{
+	int id;
+
+	/* things are taking time to settle */
+	msleep(150);
+
+	gpio_request(EFIKAMX_PCBID0, "pcbid0");
+	gpio_direction_input(EFIKAMX_PCBID0);
+	gpio_request(EFIKAMX_PCBID1, "pcbid1");
+	gpio_direction_input(EFIKAMX_PCBID1);
+	gpio_request(EFIKAMX_PCBID2, "pcbid2");
+	gpio_direction_input(EFIKAMX_PCBID2);
+
+	id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
+	id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
+	id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
+
+	switch (id) {
+	case 7:
+		system_rev = 0x11;
+		break;
+	case 6:
+		system_rev = 0x12;
+		break;
+	case 5:
+		system_rev = 0x13;
+		break;
+	case 4:
+		system_rev = 0x14;
+		break;
+	default:
+		system_rev = 0x10;
+		break;
+	}
+
+	if ((system_rev == 0x10)
+		|| (system_rev == 0x12)
+		|| (system_rev == 0x14)) {
+		printk(KERN_WARNING
+			"EfikaMX: Unsupported board revision 1.%u!\n",
+			system_rev & 0xf);
+	}
+}
+
+static struct gpio_led mx51_efikamx_leds[] __initdata = {
+	{
+		.name = "efikamx:green",
+		.default_trigger = "default-on",
+		.gpio = EFIKAMX_GREEN_LED,
+	},
+	{
+		.name = "efikamx:red",
+		.default_trigger = "ide-disk",
+		.gpio = EFIKAMX_RED_LED,
+	},
+	{
+		.name = "efikamx:blue",
+		.default_trigger = "mmc0",
+		.gpio = EFIKAMX_BLUE_LED,
+	},
+};
+
+static const struct gpio_led_platform_data
+		mx51_efikamx_leds_data __initconst = {
+	.leds = mx51_efikamx_leds,
+	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
+};
+
+static struct esdhc_platform_data sd_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct gpio_keys_button mx51_efikamx_powerkey[] = {
+	{
+		.code = KEY_POWER,
+		.gpio = EFIKAMX_POWER_KEY,
+		.type = EV_PWR,
+		.desc = "Power Button (CM)",
+		.wakeup = 1,
+		.debounce_interval = 10, /* ms */
+	},
+};
+
+static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
+	.buttons = mx51_efikamx_powerkey,
+	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
+};
+
+static void mx51_efikamx_restart(char mode, const char *cmd)
+{
+	if (system_rev == 0x11)
+		gpio_direction_output(EFIKAMX_RESET1_1, 0);
+	else
+		gpio_direction_output(EFIKAMX_RESET, 0);
+}
+
+static struct regulator *pwgt1, *pwgt2, *coincell;
+
+static void mx51_efikamx_power_off(void)
+{
+	if (!IS_ERR(coincell))
+		regulator_disable(coincell);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKAMX_POWEROFF, 1);
+}
+
+static int __init mx51_efikamx_power_init(void)
+{
+	if (machine_is_mx51_efikamx()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKAMX_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikamx_power_off;
+
+		/* enable coincell charger. maybe need a small power driver ? */
+		coincell = regulator_get(NULL, "coincell");
+		if (!IS_ERR(coincell)) {
+			regulator_set_voltage(coincell, 3000000, 3000000);
+			regulator_enable(coincell);
+		}
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikamx_power_init);
+
+static void __init mx51_efikamx_init(void)
+{
+	imx51_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
+					ARRAY_SIZE(mx51efikamx_pads));
+	efika_board_common_init();
+
+	mx51_efikamx_board_id();
+
+	/* on < 1.2 boards both SD controllers are used */
+	if (system_rev < 0x12) {
+		imx51_add_sdhci_esdhc_imx(0, NULL);
+		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
+		mx51_efikamx_leds[2].default_trigger = "mmc1";
+	} else
+		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
+
+	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
+	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
+
+	if (system_rev == 0x11) {
+		gpio_request(EFIKAMX_RESET1_1, "reset");
+		gpio_direction_output(EFIKAMX_RESET1_1, 1);
+	} else {
+		gpio_request(EFIKAMX_RESET, "reset");
+		gpio_direction_output(EFIKAMX_RESET, 1);
+	}
+
+	/*
+	 * enable wifi by default only on mx
+	 * sb and mx have same wlan pin but the value to enable it are
+	 * different :/
+	 */
+	gpio_request(EFIKA_WLAN_EN, "wlan_en");
+	gpio_direction_output(EFIKA_WLAN_EN, 0);
+	msleep(10);
+
+	gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
+	gpio_direction_output(EFIKA_WLAN_RESET, 0);
+	msleep(10);
+	gpio_set_value(EFIKA_WLAN_RESET, 1);
+}
+
+static void __init mx51_efikamx_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikamx_timer = {
+	.init = mx51_efikamx_timer_init,
+};
+
+MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
+	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.timer = &mx51_efikamx_timer,
+	.init_machine = mx51_efikamx_init,
+	.restart = mx51_efikamx_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_efikasb.c b/arch/arm/mach-imx/mach-mx51_efikasb.c
new file mode 100644
index 0000000..ea5f65b
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx51_efikasb.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+
+#define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
+#define EFIKASB_GREEN_LED	IMX_GPIO_NR(1, 3)
+#define EFIKASB_WHITE_LED	IMX_GPIO_NR(2, 25)
+#define EFIKASB_PCBID0		IMX_GPIO_NR(2, 28)
+#define EFIKASB_PCBID1		IMX_GPIO_NR(2, 29)
+#define EFIKASB_PWRKEY		IMX_GPIO_NR(2, 31)
+#define EFIKASB_LID		IMX_GPIO_NR(3, 14)
+#define EFIKASB_POWEROFF	IMX_GPIO_NR(4, 13)
+#define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
+
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
+
+static iomux_v3_cfg_t mx51efikasb_pads[] = {
+	/* USB HOST2 */
+	MX51_PAD_EIM_D16__USBH2_DATA0,
+	MX51_PAD_EIM_D17__USBH2_DATA1,
+	MX51_PAD_EIM_D18__USBH2_DATA2,
+	MX51_PAD_EIM_D19__USBH2_DATA3,
+	MX51_PAD_EIM_D20__USBH2_DATA4,
+	MX51_PAD_EIM_D21__USBH2_DATA5,
+	MX51_PAD_EIM_D22__USBH2_DATA6,
+	MX51_PAD_EIM_D23__USBH2_DATA7,
+	MX51_PAD_EIM_A24__USBH2_CLK,
+	MX51_PAD_EIM_A25__USBH2_DIR,
+	MX51_PAD_EIM_A26__USBH2_STP,
+	MX51_PAD_EIM_A27__USBH2_NXT,
+
+	/* leds */
+	MX51_PAD_EIM_CS0__GPIO2_25,
+	MX51_PAD_GPIO1_3__GPIO1_3,
+
+	/* pcb id */
+	MX51_PAD_EIM_CS3__GPIO2_28,
+	MX51_PAD_EIM_CS4__GPIO2_29,
+
+	/* lid */
+	MX51_PAD_CSI1_VSYNC__GPIO3_14,
+
+	/* power key*/
+	MX51_PAD_PWRKEY,
+
+	/* wifi/bt button */
+	MX51_PAD_DI1_PIN12__GPIO3_1,
+
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
+
+	/* wdog reset */
+	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+
+	/* BT */
+	MX51_PAD_EIM_A17__GPIO2_11,
+
+	MX51_PAD_SD1_CD,
+};
+
+static int initialize_usbh2_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
+	iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
+
+	mxc_iomux_v3_setup_pad(usbh2gpio);
+	gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
+	gpio_direction_output(EFIKASB_USBH2_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKASB_USBH2_STP, 1);
+	msleep(1);
+
+	gpio_free(EFIKASB_USBH2_STP);
+	mxc_iomux_v3_setup_pad(usbh2stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh2_config __initdata = {
+	.init   = initialize_usbh2_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void __init mx51_efikasb_usb(void)
+{
+	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+	if (usbh2_config.otg)
+		imx51_add_mxc_ehci_hs(2, &usbh2_config);
+}
+
+static const struct gpio_led mx51_efikasb_leds[] __initconst = {
+	{
+		.name = "efikasb:green",
+		.default_trigger = "default-on",
+		.gpio = EFIKASB_GREEN_LED,
+		.active_low = 1,
+	},
+	{
+		.name = "efikasb:white",
+		.default_trigger = "caps",
+		.gpio = EFIKASB_WHITE_LED,
+	},
+};
+
+static const struct gpio_led_platform_data
+		mx51_efikasb_leds_data __initconst = {
+	.leds = mx51_efikasb_leds,
+	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
+};
+
+static struct gpio_keys_button mx51_efikasb_keys[] = {
+	{
+		.code = KEY_POWER,
+		.gpio = EFIKASB_PWRKEY,
+		.type = EV_KEY,
+		.desc = "Power Button",
+		.wakeup = 1,
+		.active_low = 1,
+	},
+	{
+		.code = SW_LID,
+		.gpio = EFIKASB_LID,
+		.type = EV_SW,
+		.desc = "Lid Switch",
+		.active_low = 1,
+	},
+	{
+		.code = KEY_RFKILL,
+		.gpio = EFIKASB_RFKILL,
+		.type = EV_KEY,
+		.desc = "rfkill",
+		.active_low = 1,
+	},
+};
+
+static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
+	.buttons = mx51_efikasb_keys,
+	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
+};
+
+static struct esdhc_platform_data sd0_pdata = {
+#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
+	.cd_gpio = EFIKASB_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_type = ESDHC_CD_CONTROLLER,
+	.wp_type = ESDHC_WP_CONTROLLER,
+};
+
+static struct regulator *pwgt1, *pwgt2;
+
+static void mx51_efikasb_power_off(void)
+{
+	gpio_set_value(EFIKA_USB_PHY_RESET, 0);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKASB_POWEROFF, 1);
+}
+
+static int __init mx51_efikasb_power_init(void)
+{
+	if (machine_is_mx51_efikasb()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKASB_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikasb_power_off;
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikasb_power_init);
+
+/* 01     R1.3 board
+   10     R2.0 board */
+static void __init mx51_efikasb_board_id(void)
+{
+	int id;
+
+	gpio_request(EFIKASB_PCBID0, "pcb id0");
+	gpio_direction_input(EFIKASB_PCBID0);
+	gpio_request(EFIKASB_PCBID1, "pcb id1");
+	gpio_direction_input(EFIKASB_PCBID1);
+
+	id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
+	id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
+
+	switch (id) {
+	default:
+		break;
+	case 1:
+		system_rev = 0x13;
+		break;
+	case 2:
+		system_rev = 0x20;
+		break;
+	}
+}
+
+static void __init efikasb_board_init(void)
+{
+	imx51_soc_init();
+
+	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
+					ARRAY_SIZE(mx51efikasb_pads));
+	efika_board_common_init();
+
+	mx51_efikasb_board_id();
+	mx51_efikasb_usb();
+	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
+	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
+
+	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
+	imx_add_gpio_keys(&mx51_efikasb_keys_data);
+}
+
+static void __init mx51_efikasb_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikasb_timer = {
+	.init	= mx51_efikasb_timer_init,
+};
+
+MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+	.atag_offset = 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.handle_irq = imx51_handle_irq,
+	.init_machine =  efikasb_board_init,
+	.timer = &mx51_efikasb_timer,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
new file mode 100644
index 0000000..08dfb76
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx53_ard.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/smsc911x.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define ARD_ETHERNET_INT_B	IMX_GPIO_NR(2, 31)
+#define ARD_SD1_CD		IMX_GPIO_NR(1, 1)
+#define ARD_SD1_WP		IMX_GPIO_NR(1, 9)
+#define ARD_I2CPORTEXP_B	IMX_GPIO_NR(2, 3)
+#define ARD_VOLUMEDOWN		IMX_GPIO_NR(4, 0)
+#define ARD_HOME			IMX_GPIO_NR(5, 10)
+#define ARD_BACK			IMX_GPIO_NR(5, 11)
+#define ARD_PROG			IMX_GPIO_NR(5, 12)
+#define ARD_VOLUMEUP		IMX_GPIO_NR(5, 13)
+
+static iomux_v3_cfg_t mx53_ard_pads[] = {
+	/* UART1 */
+	MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
+	MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
+	/* WEIM for CS1 */
+	MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
+	MX53_PAD_EIM_D16__EMI_WEIM_D_16,
+	MX53_PAD_EIM_D17__EMI_WEIM_D_17,
+	MX53_PAD_EIM_D18__EMI_WEIM_D_18,
+	MX53_PAD_EIM_D19__EMI_WEIM_D_19,
+	MX53_PAD_EIM_D20__EMI_WEIM_D_20,
+	MX53_PAD_EIM_D21__EMI_WEIM_D_21,
+	MX53_PAD_EIM_D22__EMI_WEIM_D_22,
+	MX53_PAD_EIM_D23__EMI_WEIM_D_23,
+	MX53_PAD_EIM_D24__EMI_WEIM_D_24,
+	MX53_PAD_EIM_D25__EMI_WEIM_D_25,
+	MX53_PAD_EIM_D26__EMI_WEIM_D_26,
+	MX53_PAD_EIM_D27__EMI_WEIM_D_27,
+	MX53_PAD_EIM_D28__EMI_WEIM_D_28,
+	MX53_PAD_EIM_D29__EMI_WEIM_D_29,
+	MX53_PAD_EIM_D30__EMI_WEIM_D_30,
+	MX53_PAD_EIM_D31__EMI_WEIM_D_31,
+	MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
+	MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
+	MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
+	MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
+	MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
+	MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
+	MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
+	MX53_PAD_EIM_OE__EMI_WEIM_OE,
+	MX53_PAD_EIM_RW__EMI_WEIM_RW,
+	MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
+	/* SDHC1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
+	MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
+	MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
+	MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
+	MX53_PAD_GPIO_1__GPIO1_1,
+	MX53_PAD_GPIO_9__GPIO1_9,
+	/* I2C2 */
+	MX53_PAD_EIM_EB2__I2C2_SCL,
+	MX53_PAD_KEY_ROW3__I2C2_SDA,
+	/* I2C3 */
+	MX53_PAD_GPIO_3__I2C3_SCL,
+	MX53_PAD_GPIO_16__I2C3_SDA,
+	/* GPIO */
+	MX53_PAD_DISP0_DAT16__GPIO5_10,	/* home */
+	MX53_PAD_DISP0_DAT17__GPIO5_11,	/* back */
+	MX53_PAD_DISP0_DAT18__GPIO5_12,	/* prog */
+	MX53_PAD_DISP0_DAT19__GPIO5_13,	/* vol up */
+	MX53_PAD_GPIO_10__GPIO4_0,		/* vol down */
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
+{							\
+	.gpio		= gpio_num,				\
+	.type		= EV_KEY,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+	.desc		= "btn " descr,			\
+	.wakeup		= wake,					\
+}
+
+static struct gpio_keys_button ard_buttons[] = {
+	GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
+	GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
+	GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
+	GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
+	GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data ard_button_data __initconst = {
+	.buttons        = ard_buttons,
+	.nbuttons       = ARRAY_SIZE(ard_buttons),
+};
+
+static struct resource ard_smsc911x_resources[] = {
+	{
+		.start = MX53_CS1_64MB_BASE_ADDR,
+		.end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+		.end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct smsc911x_platform_config ard_smsc911x_config = {
+	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags = SMSC911X_USE_32BIT,
+};
+
+static struct platform_device ard_smsc_lan9220_device = {
+	.name = "smsc911x",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(ard_smsc911x_resources),
+	.resource = ard_smsc911x_resources,
+	.dev = {
+		.platform_data = &ard_smsc911x_config,
+	},
+};
+
+static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
+	.cd_gpio = ARD_SD1_CD,
+	.wp_gpio = ARD_SD1_WP,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c2_data = {
+	.bitrate = 50000,
+};
+
+static struct imxi2c_platform_data mx53_ard_i2c3_data = {
+	.bitrate = 400000,
+};
+
+static void __init mx53_ard_io_init(void)
+{
+	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
+	gpio_direction_input(ARD_ETHERNET_INT_B);
+
+	gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
+	gpio_direction_output(ARD_I2CPORTEXP_B, 1);
+}
+
+/* Config CS1 settings for ethernet controller */
+static int weim_cs_config(void)
+{
+	u32 reg;
+	void __iomem *weim_base, *iomuxc_base;
+
+	weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
+	if (!weim_base)
+		return -ENOMEM;
+
+	iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
+	if (!iomuxc_base)
+		return -ENOMEM;
+
+	/* CS1 timings for LAN9220 */
+	writel(0x20001, (weim_base + 0x18));
+	writel(0x0, (weim_base + 0x1C));
+	writel(0x16000202, (weim_base + 0x20));
+	writel(0x00000002, (weim_base + 0x24));
+	writel(0x16002082, (weim_base + 0x28));
+	writel(0x00000000, (weim_base + 0x2C));
+	writel(0x00000000, (weim_base + 0x90));
+
+	/* specify 64 MB on CS1 and CS0 on GPR1 */
+	reg = readl(iomuxc_base + 0x4);
+	reg &= ~0x3F;
+	reg |= 0x1B;
+	writel(reg, (iomuxc_base + 0x4));
+
+	iounmap(iomuxc_base);
+	iounmap(weim_base);
+
+	return 0;
+}
+
+void __init imx53_ard_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
+					 ARRAY_SIZE(mx53_ard_pads));
+	weim_cs_config();
+}
+
+static struct platform_device *devices[] __initdata = {
+	&ard_smsc_lan9220_device,
+};
+
+static void __init mx53_ard_board_init(void)
+{
+	imx53_soc_init();
+	imx53_add_imx_uart(0, NULL);
+
+	imx53_ard_common_init();
+	mx53_ard_io_init();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
+	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
+	imx_add_gpio_keys(&ard_button_data);
+	imx53_add_ahci_imx();
+}
+
+static void __init mx53_ard_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_ard_timer = {
+	.init	= mx53_ard_timer_init,
+};
+
+MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
+	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
+	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
+	.timer = &mx53_ard_timer,
+	.init_machine = mx53_ard_board_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c
new file mode 100644
index 0000000..5a72188
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx53_evk.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/iomux-mx53.h>
+
+#define MX53_EVK_FEC_PHY_RST	IMX_GPIO_NR(7, 6)
+#define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
+#define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
+#define MX53EVK_LED		IMX_GPIO_NR(7, 7)
+
+#include "devices-imx53.h"
+
+static iomux_v3_cfg_t mx53_evk_pads[] = {
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+	MX53_PAD_PATA_DIOR__UART2_RTS,
+	MX53_PAD_PATA_INTRQ__UART2_CTS,
+
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+
+	MX53_PAD_EIM_D16__ECSPI1_SCLK,
+	MX53_PAD_EIM_D17__ECSPI1_MISO,
+	MX53_PAD_EIM_D18__ECSPI1_MOSI,
+
+	/* ecspi chip select lines */
+	MX53_PAD_EIM_EB2__GPIO2_30,
+	MX53_PAD_EIM_D19__GPIO3_19,
+	/* LED */
+	MX53_PAD_PATA_DA_1__GPIO7_7,
+};
+
+static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const struct gpio_led mx53evk_leds[] __initconst = {
+	{
+		.name			= "green",
+		.default_trigger	= "heartbeat",
+		.gpio			= MX53EVK_LED,
+	},
+};
+
+static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
+	.leds		= mx53evk_leds,
+	.num_leds	= ARRAY_SIZE(mx53evk_leds),
+};
+
+static inline void mx53_evk_init_uart(void)
+{
+	imx53_add_imx_uart(0, NULL);
+	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(2, NULL);
+}
+
+static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static inline void mx53_evk_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
+							"fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	msleep(1);
+	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
+	{
+		.modalias = "mtd_dataflash",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_0,
+		.platform_data = NULL,
+	},
+};
+
+static int mx53_evk_spi_cs[] = {
+	EVK_ECSPI1_CS0,
+	EVK_ECSPI1_CS1,
+};
+
+static const struct spi_imx_master mx53_evk_spi_data __initconst = {
+	.chipselect     = mx53_evk_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
+};
+
+void __init imx53_evk_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
+					 ARRAY_SIZE(mx53_evk_pads));
+}
+
+static void __init mx53_evk_board_init(void)
+{
+	imx53_soc_init();
+	imx53_evk_common_init();
+
+	mx53_evk_init_uart();
+	mx53_evk_fec_reset();
+	imx53_add_fec(&mx53_evk_fec_pdata);
+
+	imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
+	imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
+
+	imx53_add_sdhci_esdhc_imx(0, NULL);
+	imx53_add_sdhci_esdhc_imx(1, NULL);
+
+	spi_register_board_info(mx53_evk_spi_board_info,
+		ARRAY_SIZE(mx53_evk_spi_board_info));
+	imx53_add_ecspi(0, &mx53_evk_spi_data);
+	imx53_add_imx2_wdt(0, NULL);
+	gpio_led_register_device(-1, &mx53evk_leds_data);
+}
+
+static void __init mx53_evk_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_evk_timer = {
+	.init	= mx53_evk_timer_init,
+};
+
+MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
+	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
+	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
+	.timer = &mx53_evk_timer,
+	.init_machine = mx53_evk_board_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c
new file mode 100644
index 0000000..37f67ca
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx53_loco.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define MX53_LOCO_POWER			IMX_GPIO_NR(1, 8)
+#define MX53_LOCO_UI1			IMX_GPIO_NR(2, 14)
+#define MX53_LOCO_UI2			IMX_GPIO_NR(2, 15)
+#define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define LOCO_LED			IMX_GPIO_NR(7, 7)
+#define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
+#define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
+#define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
+#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
+
+static iomux_v3_cfg_t mx53_loco_pads[] = {
+	/* FEC */
+	MX53_PAD_FEC_MDC__FEC_MDC,
+	MX53_PAD_FEC_MDIO__FEC_MDIO,
+	MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+	MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+	MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+	MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+	MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+	MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+	MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+	/* FEC_nRST */
+	MX53_PAD_PATA_DA_0__GPIO7_6,
+	/* FEC_nINT */
+	MX53_PAD_PATA_DATA4__GPIO2_4,
+	/* AUDMUX5 */
+	MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
+	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
+	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
+	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
+	/* I2C2 */
+	MX53_PAD_KEY_COL3__I2C2_SCL,
+	MX53_PAD_KEY_ROW3__I2C2_SDA,
+	/* SD1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD1_CD */
+	MX53_PAD_EIM_DA13__GPIO3_13,
+	/* SD3 */
+	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+	/* SD3_CD */
+	MX53_PAD_EIM_DA11__GPIO3_11,
+	/* SD3_WP */
+	MX53_PAD_EIM_DA12__GPIO3_12,
+	/* VGA */
+	MX53_PAD_EIM_OE__IPU_DI1_PIN7,
+	MX53_PAD_EIM_RW__IPU_DI1_PIN8,
+	/* DISPLB */
+	MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
+	MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
+	MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
+	MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
+	/* DISP0_POWER_EN */
+	MX53_PAD_EIM_D24__GPIO3_24,
+	/* DISP0 DET INT */
+	MX53_PAD_EIM_D31__GPIO3_31,
+	/* LVDS */
+	MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+	MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+	MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+	MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+	MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+	MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+	MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+	MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+	MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+	MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	/* UART1 */
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+	/* CSI0 */
+	MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
+	MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
+	MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
+	MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
+	MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
+	MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
+	MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
+	MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
+	MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
+	MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
+	MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
+	/* DISPLAY */
+	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+	/* Audio CLK*/
+	MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
+	/* PWM */
+	MX53_PAD_GPIO_1__PWM2_PWMO,
+	/* SPDIF */
+	MX53_PAD_GPIO_7__SPDIF_PLOCK,
+	MX53_PAD_GPIO_17__SPDIF_OUT1,
+	/* GPIO */
+	MX53_PAD_PATA_DA_1__GPIO7_7,		/* LED */
+	MX53_PAD_PATA_DA_2__GPIO7_8,
+	MX53_PAD_PATA_DATA5__GPIO2_5,
+	MX53_PAD_PATA_DATA6__GPIO2_6,
+	MX53_PAD_PATA_DATA14__GPIO2_14,
+	MX53_PAD_PATA_DATA15__GPIO2_15,
+	MX53_PAD_PATA_INTRQ__GPIO7_2,
+	MX53_PAD_EIM_WAIT__GPIO5_0,
+	MX53_PAD_NANDF_WP_B__GPIO6_9,
+	MX53_PAD_NANDF_RB0__GPIO6_10,
+	MX53_PAD_NANDF_CS1__GPIO6_14,
+	MX53_PAD_NANDF_CS2__GPIO6_15,
+	MX53_PAD_NANDF_CS3__GPIO6_16,
+	MX53_PAD_GPIO_5__GPIO1_5,
+	MX53_PAD_GPIO_16__GPIO7_11,
+	MX53_PAD_GPIO_8__GPIO1_8,
+};
+
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
+{								\
+	.gpio		= gpio_num,				\
+	.type		= EV_KEY,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+	.desc		= "btn " descr,				\
+	.wakeup		= wake,					\
+}
+
+static struct gpio_keys_button loco_buttons[] = {
+	GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
+	GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
+	GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
+};
+
+static const struct gpio_keys_platform_data loco_button_data __initconst = {
+	.buttons        = loco_buttons,
+	.nbuttons       = ARRAY_SIZE(loco_buttons),
+};
+
+static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
+	.cd_gpio = LOCO_SD1_CD,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_NONE,
+};
+
+static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
+	.cd_gpio = LOCO_SD3_CD,
+	.wp_gpio = LOCO_SD3_WP,
+	.cd_type = ESDHC_CD_GPIO,
+	.wp_type = ESDHC_WP_GPIO,
+};
+
+static inline void mx53_loco_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(LOCO_FEC_PHY_RST, 0);
+	msleep(1);
+	gpio_set_value(LOCO_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_loco_fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static const struct gpio_led mx53loco_leds[] __initconst = {
+	{
+		.name			= "green",
+		.default_trigger	= "heartbeat",
+		.gpio			= LOCO_LED,
+	},
+};
+
+static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
+	.leds		= mx53loco_leds,
+	.num_leds	= ARRAY_SIZE(mx53loco_leds),
+};
+
+void __init imx53_qsb_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
+					 ARRAY_SIZE(mx53_loco_pads));
+}
+
+static struct i2c_board_info mx53loco_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("mma8450", 0x1C),
+	},
+};
+
+static void __init mx53_loco_board_init(void)
+{
+	int ret;
+	imx53_soc_init();
+	imx53_qsb_common_init();
+
+	imx53_add_imx_uart(0, NULL);
+	mx53_loco_fec_reset();
+	imx53_add_fec(&mx53_loco_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+
+	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
+	if (ret)
+		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
+
+	i2c_register_board_info(0, mx53loco_i2c_devices,
+				ARRAY_SIZE(mx53loco_i2c_devices));
+	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
+	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
+	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
+	imx_add_gpio_keys(&loco_button_data);
+	gpio_led_register_device(-1, &mx53loco_leds_data);
+	imx53_add_ahci_imx();
+}
+
+static void __init mx53_loco_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 0, 0);
+}
+
+static struct sys_timer mx53_loco_timer = {
+	.init	= mx53_loco_timer_init,
+};
+
+MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
+	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
+	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
+	.timer = &mx53_loco_timer,
+	.init_machine = mx53_loco_board_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c
new file mode 100644
index 0000000..8e972c5
--- /dev/null
+++ b/arch/arm/mach-imx/mach-mx53_smd.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx53.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx53.h"
+
+#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
+
+static iomux_v3_cfg_t mx53_smd_pads[] = {
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+	MX53_PAD_PATA_DA_1__UART3_CTS,
+	MX53_PAD_PATA_DA_2__UART3_RTS,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	/* SD1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD2 */
+	MX53_PAD_SD2_CMD__ESDHC2_CMD,
+	MX53_PAD_SD2_CLK__ESDHC2_CLK,
+	MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
+	MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
+	MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
+	MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
+	/* SD3 */
+	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+};
+
+static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static inline void mx53_smd_init_uart(void)
+{
+	imx53_add_imx_uart(0, NULL);
+	imx53_add_imx_uart(1, NULL);
+	imx53_add_imx_uart(2, &mx53_smd_uart_data);
+}
+
+static inline void mx53_smd_fec_reset(void)
+{
+	int ret;
+
+	/* reset FEC PHY */
+	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(SMD_FEC_PHY_RST, 0);
+	msleep(1);
+	gpio_set_value(SMD_FEC_PHY_RST, 1);
+}
+
+static const struct fec_platform_data mx53_smd_fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
+static inline void mx53_smd_ahci_pwr_on(void)
+{
+	int ret;
+
+	/* Enable SATA PWR */
+	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
+			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
+	if (ret) {
+		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
+		return;
+	}
+}
+
+void __init imx53_smd_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
+					 ARRAY_SIZE(mx53_smd_pads));
+}
+
+static void __init mx53_smd_board_init(void)
+{
+	imx53_soc_init();
+	imx53_smd_common_init();
+
+	mx53_smd_init_uart();
+	mx53_smd_fec_reset();
+	imx53_add_fec(&mx53_smd_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
+	imx53_add_sdhci_esdhc_imx(0, NULL);
+	imx53_add_sdhci_esdhc_imx(1, NULL);
+	imx53_add_sdhci_esdhc_imx(2, NULL);
+	mx53_smd_ahci_pwr_on();
+	imx53_add_ahci_imx();
+}
+
+static void __init mx53_smd_timer_init(void)
+{
+	mx53_clocks_init(32768, 24000000, 22579200, 0);
+}
+
+static struct sys_timer mx53_smd_timer = {
+	.init	= mx53_smd_timer_init,
+};
+
+MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
+	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
+	.init_irq = mx53_init_irq,
+	.handle_irq = imx53_handle_irq,
+	.timer = &mx53_smd_timer,
+	.init_machine = mx53_smd_board_init,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
new file mode 100644
index 0000000..bc17dfe
--- /dev/null
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License.  You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * Create static mapping between physical to virtual memory.
+ */
+
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/devices-common.h>
+#include <mach/iomux-v3.h>
+
+static struct clk *gpc_dvfs_clk;
+
+static void imx5_idle(void)
+{
+	if (!need_resched()) {
+		/* gpc clock is needed for SRPG */
+		if (gpc_dvfs_clk == NULL) {
+			gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+			if (IS_ERR(gpc_dvfs_clk))
+				goto err0;
+		}
+		clk_enable(gpc_dvfs_clk);
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+		if (tzic_enable_wake())
+			goto err1;
+		cpu_do_idle();
+err1:
+		clk_disable(gpc_dvfs_clk);
+	}
+err0:
+	local_irq_enable();
+}
+
+/*
+ * Define the MX50 memory map.
+ */
+static struct map_desc mx50_io_desc[] __initdata = {
+	imx_map_entry(MX50, TZIC, MT_DEVICE),
+	imx_map_entry(MX50, SPBA0, MT_DEVICE),
+	imx_map_entry(MX50, AIPS1, MT_DEVICE),
+	imx_map_entry(MX50, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX51 memory map.
+ */
+static struct map_desc mx51_io_desc[] __initdata = {
+	imx_map_entry(MX51, TZIC, MT_DEVICE),
+	imx_map_entry(MX51, IRAM, MT_DEVICE),
+	imx_map_entry(MX51, AIPS1, MT_DEVICE),
+	imx_map_entry(MX51, SPBA0, MT_DEVICE),
+	imx_map_entry(MX51, AIPS2, MT_DEVICE),
+};
+
+/*
+ * Define the MX53 memory map.
+ */
+static struct map_desc mx53_io_desc[] __initdata = {
+	imx_map_entry(MX53, TZIC, MT_DEVICE),
+	imx_map_entry(MX53, AIPS1, MT_DEVICE),
+	imx_map_entry(MX53, SPBA0, MT_DEVICE),
+	imx_map_entry(MX53, AIPS2, MT_DEVICE),
+};
+
+/*
+ * This function initializes the memory map. It is called during the
+ * system startup to create static physical to virtual memory mappings
+ * for the IO modules.
+ */
+void __init mx50_map_io(void)
+{
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+void __init mx51_map_io(void)
+{
+	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+void __init mx53_map_io(void)
+{
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX50);
+	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
+}
+
+void __init imx51_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX51);
+	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
+	pm_idle = imx5_idle;
+}
+
+void __init imx53_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX53);
+	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
+}
+
+void __init mx50_init_irq(void)
+{
+	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
+}
+
+void __init mx51_init_irq(void)
+{
+	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
+}
+
+void __init mx53_init_irq(void)
+{
+	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+}
+
+static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.uart_2_mcu_addr = 817,
+	.mcu_2_app_addr = 747,
+	.mcu_2_shp_addr = 961,
+	.ata_2_mcu_addr = 1473,
+	.mcu_2_ata_addr = 1392,
+	.app_2_per_addr = 1033,
+	.app_2_mcu_addr = 683,
+	.shp_2_per_addr = 1251,
+	.shp_2_mcu_addr = 892,
+};
+
+static struct sdma_platform_data imx51_sdma_pdata __initdata = {
+	.fw_name = "sdma-imx51.bin",
+	.script_addrs = &imx51_sdma_script,
+};
+
+static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
+	.ap_2_ap_addr = 642,
+	.app_2_mcu_addr = 683,
+	.mcu_2_app_addr = 747,
+	.uart_2_mcu_addr = 817,
+	.shp_2_mcu_addr = 891,
+	.mcu_2_shp_addr = 960,
+	.uartsh_2_mcu_addr = 1032,
+	.spdif_2_mcu_addr = 1100,
+	.mcu_2_spdif_addr = 1134,
+	.firi_2_mcu_addr = 1193,
+	.mcu_2_firi_addr = 1290,
+};
+
+static struct sdma_platform_data imx53_sdma_pdata __initdata = {
+	.fw_name = "sdma-imx53.bin",
+	.script_addrs = &imx53_sdma_script,
+};
+
+void __init imx50_soc_init(void)
+{
+	/* i.mx50 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
+}
+
+void __init imx51_soc_init(void)
+{
+	/* i.mx51 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
+
+	/* i.mx51 has the i.mx35 type sdma */
+	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
+}
+
+void __init imx53_soc_init(void)
+{
+	/* i.mx53 has the i.mx31 type gpio */
+	mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
+	mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
+	mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
+	mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
+	mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
+	mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
+	mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
+
+	/* i.mx53 has the i.mx35 type sdma */
+	imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
+}
diff --git a/arch/arm/mach-imx/mx51_efika.c b/arch/arm/mach-imx/mx51_efika.c
new file mode 100644
index 0000000..ec6ca91
--- /dev/null
+++ b/arch/arm/mach-imx/mx51_efika.c
@@ -0,0 +1,632 @@
+/*
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "efika.h"
+#include "cpu_op-mx51.h"
+
+#define MX51_USB_CTRL_1_OFFSET          0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+
+#define EFIKAMX_USB_HUB_RESET	IMX_GPIO_NR(1, 5)
+#define EFIKAMX_USBH1_STP	IMX_GPIO_NR(1, 27)
+
+#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
+static iomux_v3_cfg_t mx51efika_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+	/* SD/MMC WP/CD */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
+	MX51_PAD_GPIO1_7__SD2_WP,
+	MX51_PAD_GPIO1_8__SD2_CD,
+
+	/* spi */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_GPIO1_6__GPIO1_6,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+	/* USB HUB RESET */
+	MX51_PAD_GPIO1_5__GPIO1_5,
+
+	/* WLAN */
+	MX51_PAD_EIM_A22__GPIO2_16,
+	MX51_PAD_EIM_A16__GPIO2_10,
+
+	/* USB PHY RESET */
+	MX51_PAD_EIM_D27__GPIO2_9,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
+static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
+	.init   = initialize_otg_port,
+	.portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+	iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *socregs_base;
+
+	mxc_iomux_v3_setup_pad(usbh1gpio);
+	gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
+	gpio_direction_output(EFIKAMX_USBH1_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USBH1_STP, 1);
+	msleep(1);
+
+	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
+	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* The clock for the USBH1 ULPI port will come externally */
+	/* from the PHY. */
+	v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+			socregs_base + MX51_USB_CTRL_1_OFFSET);
+
+	iounmap(usb_base);
+
+	gpio_free(EFIKAMX_USBH1_STP);
+	mxc_iomux_v3_setup_pad(usbh1stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh1_config __initdata = {
+	.init   = initialize_usbh1_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void mx51_efika_hubreset(void)
+{
+	gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
+	gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
+}
+
+static void __init mx51_efika_usb(void)
+{
+	mx51_efika_hubreset();
+
+	/* pulling it low, means no USB at all... */
+	gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
+	gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKA_USB_PHY_RESET, 1);
+
+	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+
+	imx51_add_mxc_ehci_otg(&dr_utmi_config);
+	if (usbh1_config.otg)
+		imx51_add_mxc_ehci_hs(1, &usbh1_config);
+}
+
+static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
+	{
+	 .name = "u-boot",
+	 .offset = 0,
+	 .size = SZ_256K,
+	},
+	{
+	  .name = "config",
+	  .offset = MTDPART_OFS_APPEND,
+	  .size = SZ_64K,
+	},
+};
+
+static struct flash_platform_data mx51_efika_spi_flash_data = {
+	.name		= "spi_flash",
+	.parts		= mx51_efika_spi_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(mx51_efika_spi_nor_partitions),
+	.type		= "sst25vf032b",
+};
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+	{
+		.supply = "cpu_vcc",
+	}
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDA", "1-000a"),
+	REGULATOR_SUPPLY("VDDD", "1-000a"),
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDIO", "1-000a"),
+};
+
+static struct regulator_consumer_supply vsd_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
+};
+
+static struct regulator_consumer_supply pwgt1_consumer[] = {
+	{
+		.supply = "pwgt1",
+	}
+};
+
+static struct regulator_consumer_supply pwgt2_consumer[] = {
+	{
+		.supply = "pwgt2",
+	}
+};
+
+static struct regulator_consumer_supply coincell_consumer[] = {
+	{
+		.supply = "coincell",
+	}
+};
+
+static struct regulator_init_data sw1_init = {
+	.constraints = {
+		.name = "SW1",
+		.min_uV = 600000,
+		.max_uV = 1375000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.valid_modes_mask = 0,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 850000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+	.consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+	.constraints = {
+		.name = "SW2",
+		.min_uV = 900000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 950000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	}
+};
+
+static struct regulator_init_data sw3_init = {
+	.constraints = {
+		.name = "SW3",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data sw4_init = {
+	.constraints = {
+		.name = "SW4",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data viohi_init = {
+	.constraints = {
+		.name = "VIOHI",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb_init = {
+	.constraints = {
+		.name = "VUSB",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data swbst_init = {
+	.constraints = {
+		.name = "SWBST",
+	}
+};
+
+static struct regulator_init_data vdig_init = {
+	.constraints = {
+		.name = "VDIG",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+	.consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+	.constraints = {
+		.name = "VPLL",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb2_init = {
+	.constraints = {
+		.name = "VUSB2",
+		.min_uV = 2400000,
+		.max_uV = 2775000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vvideo_init = {
+	.constraints = {
+		.name = "VVIDEO",
+		.min_uV = 2775000,
+		.max_uV = 2775000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.apply_uV = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+	.consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+	.constraints = {
+		.name = "VAUDIO",
+		.min_uV = 2300000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vsd_init = {
+	.constraints = {
+		.name = "VSD",
+		.min_uV = 1800000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
+	.consumer_supplies = vsd_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+	.constraints = {
+		.name = "VCAM",
+		.min_uV = 2500000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen1_init = {
+	.constraints = {
+		.name = "VGEN1",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen2_init = {
+	.constraints = {
+		.name = "VGEN2",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen3_init = {
+	.constraints = {
+		.name = "VGEN3",
+		.min_uV = 1800000,
+		.max_uV = 2900000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data gpo1_init = {
+	.constraints = {
+		.name = "GPO1",
+	}
+};
+
+static struct regulator_init_data gpo2_init = {
+	.constraints = {
+		.name = "GPO2",
+	}
+};
+
+static struct regulator_init_data gpo3_init = {
+	.constraints = {
+		.name = "GPO3",
+	}
+};
+
+static struct regulator_init_data gpo4_init = {
+	.constraints = {
+		.name = "GPO4",
+	}
+};
+
+static struct regulator_init_data pwgt1_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
+	.consumer_supplies = pwgt1_consumer,
+};
+
+static struct regulator_init_data pwgt2_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
+	.consumer_supplies = pwgt2_consumer,
+};
+
+static struct regulator_init_data vcoincell_init = {
+	.constraints = {
+		.name = "COINCELL",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
+	.consumer_supplies = coincell_consumer,
+};
+
+static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
+	{ .id = MC13892_SW1,		.init_data =  &sw1_init },
+	{ .id = MC13892_SW2,		.init_data =  &sw2_init },
+	{ .id = MC13892_SW3,		.init_data =  &sw3_init },
+	{ .id = MC13892_SW4,		.init_data =  &sw4_init },
+	{ .id = MC13892_SWBST,		.init_data =  &swbst_init },
+	{ .id = MC13892_VIOHI,		.init_data =  &viohi_init },
+	{ .id = MC13892_VPLL,		.init_data =  &vpll_init },
+	{ .id = MC13892_VDIG,		.init_data =  &vdig_init },
+	{ .id = MC13892_VSD,		.init_data =  &vsd_init },
+	{ .id = MC13892_VUSB2,		.init_data =  &vusb2_init },
+	{ .id = MC13892_VVIDEO,		.init_data =  &vvideo_init },
+	{ .id = MC13892_VAUDIO,		.init_data =  &vaudio_init },
+	{ .id = MC13892_VCAM,		.init_data =  &vcam_init },
+	{ .id = MC13892_VGEN1,		.init_data =  &vgen1_init },
+	{ .id = MC13892_VGEN2,		.init_data =  &vgen2_init },
+	{ .id = MC13892_VGEN3,		.init_data =  &vgen3_init },
+	{ .id = MC13892_VUSB,		.init_data =  &vusb_init },
+	{ .id = MC13892_GPO1,		.init_data =  &gpo1_init },
+	{ .id = MC13892_GPO2,		.init_data =  &gpo2_init },
+	{ .id = MC13892_GPO3,		.init_data =  &gpo3_init },
+	{ .id = MC13892_GPO4,		.init_data =  &gpo4_init },
+	{ .id = MC13892_PWGT1SPI,	.init_data = &pwgt1_init },
+	{ .id = MC13892_PWGT2SPI,	.init_data = &pwgt2_init },
+	{ .id = MC13892_VCOINCELL,	.init_data = &vcoincell_init },
+};
+
+static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
+	.flags = MC13XXX_USE_RTC,
+	.regulators = {
+		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
+		.regulators = mx51_efika_regulators,
+	},
+};
+
+static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &mx51_efika_spi_flash_data,
+		.irq = -1,
+	},
+	{
+		.modalias = "mc13892",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.platform_data = &mx51_efika_mc13892_data,
+		.irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
+	},
+};
+
+static int mx51_efika_spi_cs[] = {
+	EFIKAMX_SPI_CS0,
+	EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
+	.chipselect     = mx51_efika_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
+};
+
+void __init efika_board_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
+					ARRAY_SIZE(mx51efika_pads));
+	imx51_add_imx_uart(0, &uart_pdata);
+	mx51_efika_usb();
+
+	/* FIXME: comes from original code. check this. */
+	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
+		sw2_init.constraints.state_mem.uV = 1100000;
+	else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
+		sw2_init.constraints.state_mem.uV = 1250000;
+		sw1_init.constraints.state_mem.uV = 1000000;
+	}
+	if (machine_is_mx51_efikasb())
+		vgen1_init.constraints.max_uV = 1200000;
+
+	gpio_request(EFIKAMX_PMIC, "pmic irq");
+	gpio_direction_input(EFIKAMX_PMIC);
+	spi_register_board_info(mx51_efika_spi_board_info,
+		ARRAY_SIZE(mx51_efika_spi_board_info));
+	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+
+	imx51_add_pata_imx();
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+}
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
new file mode 100644
index 0000000..6dc0934
--- /dev/null
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -0,0 +1,153 @@
+/*
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include "crm-regs-imx5.h"
+
+static struct clk *gpc_dvfs_clk;
+
+/*
+ * set cpu low power mode before WFI instruction. This function is called
+ * mx5 because it can be used for mx50, mx51, and mx53.
+ */
+void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+	u32 plat_lpc, arm_srpgcr, ccm_clpcr;
+	u32 empgc0, empgc1;
+	int stop_mode = 0;
+
+	/* always allow platform to issue a deep sleep mode request */
+	plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
+	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
+	empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
+	empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+	case STOP_POWER_OFF:
+		plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
+			    | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
+		if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+			ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+			ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+			ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+			stop_mode = 0;
+		} else {
+			ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+			ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+			ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+			ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+			stop_mode = 1;
+		}
+		arm_srpgcr |= MXC_SRPGCR_PCR;
+		break;
+	case STOP_POWER_ON:
+		ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+		break;
+	default:
+		printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+		return;
+	}
+
+	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
+
+	/* Enable NEON SRPG for all but MX50TO1.0. */
+	if (mx50_revision() != IMX_CHIP_REVISION_1_0)
+		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+
+	if (stop_mode) {
+		empgc0 |= MXC_SRPGCR_PCR;
+		empgc1 |= MXC_SRPGCR_PCR;
+
+		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+	}
+}
+
+static int mx5_suspend_prepare(void)
+{
+	return clk_enable(gpc_dvfs_clk);
+}
+
+static int mx5_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		mx5_cpu_lp_set(STOP_POWER_OFF);
+		break;
+	case PM_SUSPEND_STANDBY:
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (state == PM_SUSPEND_MEM) {
+		local_flush_tlb_all();
+		flush_cache_all();
+
+		/*clear the EMPGC0/1 bits */
+		__raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
+	}
+	cpu_do_idle();
+	return 0;
+}
+
+static void mx5_suspend_finish(void)
+{
+	clk_disable(gpc_dvfs_clk);
+}
+
+static int mx5_pm_valid(suspend_state_t state)
+{
+	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+static const struct platform_suspend_ops mx5_suspend_ops = {
+	.valid = mx5_pm_valid,
+	.prepare = mx5_suspend_prepare,
+	.enter = mx5_suspend_enter,
+	.finish = mx5_suspend_finish,
+};
+
+static int __init mx5_pm_init(void)
+{
+	if (!cpu_is_mx51() && !cpu_is_mx53())
+		return 0;
+
+	if (gpc_dvfs_clk == NULL)
+		gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+	if (!IS_ERR(gpc_dvfs_clk)) {
+		if (cpu_is_mx51())
+			suspend_set_ops(&mx5_suspend_ops);
+	} else
+		return -EPERM;
+
+	return 0;
+}
+device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
deleted file mode 100644
index af0c212..0000000
--- a/arch/arm/mach-mx5/Kconfig
+++ /dev/null
@@ -1,244 +0,0 @@
-if ARCH_MX5
-
-# ARCH_MX5/50/53 are left to mark places where prevent multi-soc in single
-# image. So for most time, SOC_IMX50/51/53 should be used.
-
-config ARCH_MX51
-	bool
-
-config ARCH_MX50
-	bool
-
-config ARCH_MX53
-	bool
-
-config SOC_IMX50
-	bool
-	select CPU_V7
-	select ARM_L1_CACHE_SHIFT_6
-	select MXC_TZIC
-	select ARCH_MXC_IOMUX_V3
-	select ARCH_MXC_AUDMUX_V2
-	select ARCH_HAS_CPUFREQ
-	select ARCH_MX50
-
-config	SOC_IMX51
-	bool
-	select CPU_V7
-	select ARM_L1_CACHE_SHIFT_6
-	select MXC_TZIC
-	select ARCH_MXC_IOMUX_V3
-	select ARCH_MXC_AUDMUX_V2
-	select ARCH_HAS_CPUFREQ
-	select ARCH_MX51
-
-config	SOC_IMX53
-	bool
-	select CPU_V7
-	select ARM_L1_CACHE_SHIFT_6
-	select MXC_TZIC
-	select ARCH_MXC_IOMUX_V3
-	select ARCH_MX53
-
-#comment "i.MX50 machines:"
-
-config MACH_MX50_RDP
-	bool "Support MX50 reference design platform"
-	depends on BROKEN
-	select SOC_IMX50
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	help
-	  Include support for MX50 reference design platform (RDP) board. This
-	  includes specific configurations for the board and its peripherals.
-
-comment "i.MX51 machines:"
-
-config MACH_IMX51_DT
-	bool "Support i.MX51 platforms from device tree"
-	select SOC_IMX51
-	select USE_OF
-	select MACH_MX51_BABBAGE
-	help
-	  Include support for Freescale i.MX51 based platforms
-	  using the device tree for discovery
-
-config MACH_MX51_BABBAGE
-	bool "Support MX51 BABBAGE platforms"
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	help
-	  Include support for MX51 Babbage platform, also known as MX51EVK in
-	  u-boot. This includes specific configurations for the board and its
-	  peripherals.
-
-config MACH_MX51_3DS
-	bool "Support MX51PDK (3DS)"
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_KEYPAD
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select MXC_DEBUG_BOARD
-	help
-	  Include support for MX51PDK (3DS) platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_EUKREA_CPUIMX51
-	bool "Support Eukrea CPUIMX51 module"
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	help
-	  Include support for Eukrea CPUIMX51 platform. This includes
-	  specific configurations for the module and its peripherals.
-
-choice
-	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX51
-	default MACH_EUKREA_MBIMX51_BASEBOARD
-
-config MACH_EUKREA_MBIMX51_BASEBOARD
-	prompt "Eukrea MBIMX51 development board"
-	bool
-	select IMX_HAVE_PLATFORM_IMX_KEYPAD
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select LEDS_GPIO_REGISTER
-	help
-	  This adds board specific devices that can be found on Eukrea's
-	  MBIMX51 evaluation board.
-
-endchoice
-
-config MACH_EUKREA_CPUIMX51SD
-	bool "Support Eukrea CPUIMX51SD module"
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_MXC_NAND
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	help
-	  Include support for Eukrea CPUIMX51SD platform. This includes
-	  specific configurations for the module and its peripherals.
-
-choice
-	prompt "Baseboard"
-	depends on MACH_EUKREA_CPUIMX51SD
-	default MACH_EUKREA_MBIMXSD51_BASEBOARD
-
-config MACH_EUKREA_MBIMXSD51_BASEBOARD
-	prompt "Eukrea MBIMXSD development board"
-	bool
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select LEDS_GPIO_REGISTER
-	help
-	  This adds board specific devices that can be found on Eukrea's
-	  MBIMXSD evaluation board.
-
-endchoice
-
-config MX51_EFIKA_COMMON
-	bool
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_PATA_IMX
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select MXC_ULPI if USB_ULPI
-
-config MACH_MX51_EFIKAMX
-	bool "Support MX51 Genesi Efika MX nettop"
-	select LEDS_GPIO_REGISTER
-	select MX51_EFIKA_COMMON
-	help
-	  Include support for Genesi Efika MX nettop. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX51_EFIKASB
-	bool "Support MX51 Genesi Efika Smartbook"
-	select LEDS_GPIO_REGISTER
-	select MX51_EFIKA_COMMON
-	help
-	  Include support for Genesi Efika Smartbook. This includes specific
-	  configurations for the board and its peripherals.
-
-comment "i.MX53 machines:"
-
-config MACH_IMX53_DT
-	bool "Support i.MX53 platforms from device tree"
-	select SOC_IMX53
-	select USE_OF
-	select MACH_MX53_ARD
-	select MACH_MX53_EVK
-	select MACH_MX53_LOCO
-	select MACH_MX53_SMD
-	help
-	  Include support for Freescale i.MX53 based platforms
-	  using the device tree for discovery
-
-config MACH_MX53_EVK
-	bool "Support MX53 EVK platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select LEDS_GPIO_REGISTER
-	help
-	  Include support for MX53 EVK platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX53_SMD
-	bool "Support MX53 SMD platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	help
-	  Include support for MX53 SMD platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX53_LOCO
-	bool "Support MX53 LOCO platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_GPIO_KEYS
-	select LEDS_GPIO_REGISTER
-	help
-	  Include support for MX53 LOCO platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX53_ARD
-	bool "Support MX53 ARD platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_GPIO_KEYS
-	help
-	  Include support for MX53 ARD platform. This includes specific
-	  configurations for the board and its peripherals.
-
-endif
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
deleted file mode 100644
index 0fc6080..0000000
--- a/arch/arm/mach-mx5/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o ehci.o system.o
-
-obj-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
-obj-$(CONFIG_MACH_MX51_BABBAGE) += board-mx51_babbage.o
-obj-$(CONFIG_MACH_MX51_3DS) += board-mx51_3ds.o
-obj-$(CONFIG_MACH_MX53_EVK) += board-mx53_evk.o
-obj-$(CONFIG_MACH_MX53_SMD) += board-mx53_smd.o
-obj-$(CONFIG_MACH_MX53_LOCO) += board-mx53_loco.o
-obj-$(CONFIG_MACH_MX53_ARD) += board-mx53_ard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
-obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
-obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
-obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
-obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
-obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
-obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
-obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
-
-obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
-obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
diff --git a/arch/arm/mach-mx5/Makefile.boot b/arch/arm/mach-mx5/Makefile.boot
deleted file mode 100644
index ca207ca..0000000
--- a/arch/arm/mach-mx5/Makefile.boot
+++ /dev/null
@@ -1,9 +0,0 @@
-   zreladdr-$(CONFIG_ARCH_MX50)	+= 0x70008000
-params_phys-$(CONFIG_ARCH_MX50)	:= 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX50)	:= 0x70800000
-   zreladdr-$(CONFIG_ARCH_MX51)	+= 0x90008000
-params_phys-$(CONFIG_ARCH_MX51)	:= 0x90000100
-initrd_phys-$(CONFIG_ARCH_MX51)	:= 0x90800000
-   zreladdr-$(CONFIG_ARCH_MX53)	+= 0x70008000
-params_phys-$(CONFIG_ARCH_MX53)	:= 0x70000100
-initrd_phys-$(CONFIG_ARCH_MX53)	:= 0x70800000
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
deleted file mode 100644
index 944025d..0000000
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-
-#define CPUIMX51_USBH1_STP	IMX_GPIO_NR(1, 27)
-#define CPUIMX51_QUARTA_GPIO	IMX_GPIO_NR(3, 28)
-#define CPUIMX51_QUARTB_GPIO	IMX_GPIO_NR(3, 25)
-#define CPUIMX51_QUARTC_GPIO	IMX_GPIO_NR(3, 26)
-#define CPUIMX51_QUARTD_GPIO	IMX_GPIO_NR(3, 27)
-#define CPUIMX51_QUART_XTAL	14745600
-#define CPUIMX51_QUART_REGSHIFT	17
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET		0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)
-
-#define	MX51_USB_PLLDIV_12_MHZ		0x00
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-#define	MX51_USB_PLL_DIV_24_MHZ		0x02
-
-static struct plat_serial8250_port serial_platform_data[] = {
-	{
-		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
-		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTA_GPIO),
-		.irqflags = IRQF_TRIGGER_HIGH,
-		.uartclk = CPUIMX51_QUART_XTAL,
-		.regshift = CPUIMX51_QUART_REGSHIFT,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x800000),
-		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTB_GPIO),
-		.irqflags = IRQF_TRIGGER_HIGH,
-		.uartclk = CPUIMX51_QUART_XTAL,
-		.regshift = CPUIMX51_QUART_REGSHIFT,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x1000000),
-		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTC_GPIO),
-		.irqflags = IRQF_TRIGGER_HIGH,
-		.uartclk = CPUIMX51_QUART_XTAL,
-		.regshift = CPUIMX51_QUART_REGSHIFT,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x2000000),
-		.irq = IMX_GPIO_TO_IRQ(CPUIMX51_QUARTD_GPIO),
-		.irqflags = IRQF_TRIGGER_HIGH,
-		.uartclk = CPUIMX51_QUART_XTAL,
-		.regshift = CPUIMX51_QUART_REGSHIFT,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
-	}, {
-	}
-};
-
-static struct platform_device serial_device = {
-	.name = "serial8250",
-	.id = 0,
-	.dev = {
-		.platform_data = serial_platform_data,
-	},
-};
-
-static struct platform_device *devices[] __initdata = {
-	&serial_device,
-};
-
-static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* I2C2 */
-	MX51_PAD_GPIO1_2__I2C2_SCL,
-	MX51_PAD_GPIO1_3__I2C2_SDA,
-	MX51_PAD_NANDF_D10__GPIO3_30,
-
-	/* QUART IRQ */
-	MX51_PAD_NANDF_D15__GPIO3_25,
-	MX51_PAD_NANDF_D14__GPIO3_26,
-	MX51_PAD_NANDF_D13__GPIO3_27,
-	MX51_PAD_NANDF_D12__GPIO3_28,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-	MX51_PAD_USBH1_STP__USBH1_STP,
-};
-
-static const struct mxc_nand_platform_data
-		eukrea_cpuimx51_nand_board_info __initconst = {
-	.width		= 1,
-	.hw_ecc		= 1,
-	.flash_bbt	= 1,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const
-struct imxi2c_platform_data eukrea_cpuimx51_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static struct i2c_board_info eukrea_cpuimx51_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	},
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
-	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-			MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init		= initialize_otg_port,
-	.portsc	= MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-	.init		= initialize_usbh1_port,
-	.portsc	= MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51_otg_mode(char *options)
-{
-	if (!strcmp(options, "host"))
-		otg_mode_host = 1;
-	else if (!strcmp(options, "device"))
-		otg_mode_host = 0;
-	else
-		pr_info("otg_mode neither \"host\" nor \"device\". "
-			"Defaulting to device\n");
-	return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51_otg_mode);
-
-/*
- * Board specific initialization.
- */
-static void __init eukrea_cpuimx51_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads,
-					ARRAY_SIZE(eukrea_cpuimx51_pads));
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_mxc_nand(&eukrea_cpuimx51_nand_board_info);
-
-	gpio_request(CPUIMX51_QUARTA_GPIO, "quarta_irq");
-	gpio_direction_input(CPUIMX51_QUARTA_GPIO);
-	gpio_free(CPUIMX51_QUARTA_GPIO);
-	gpio_request(CPUIMX51_QUARTB_GPIO, "quartb_irq");
-	gpio_direction_input(CPUIMX51_QUARTB_GPIO);
-	gpio_free(CPUIMX51_QUARTB_GPIO);
-	gpio_request(CPUIMX51_QUARTC_GPIO, "quartc_irq");
-	gpio_direction_input(CPUIMX51_QUARTC_GPIO);
-	gpio_free(CPUIMX51_QUARTC_GPIO);
-	gpio_request(CPUIMX51_QUARTD_GPIO, "quartd_irq");
-	gpio_direction_input(CPUIMX51_QUARTD_GPIO);
-	gpio_free(CPUIMX51_QUARTD_GPIO);
-
-	imx51_add_fec(NULL);
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	imx51_add_imx_i2c(1, &eukrea_cpuimx51_i2c_data);
-	i2c_register_board_info(1, eukrea_cpuimx51_i2c_devices,
-				ARRAY_SIZE(eukrea_cpuimx51_i2c_devices));
-
-	if (otg_mode_host)
-		imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	else {
-		initialize_otg_port(NULL);
-		imx51_add_fsl_usb2_udc(&usb_pdata);
-	}
-	imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD
-	eukrea_mbimx51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
-	.init	= eukrea_cpuimx51_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
-	/* Maintainer: Eric Bénard <eric@eukrea.com> */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mxc_timer,
-	.init_machine = eukrea_cpuimx51_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
deleted file mode 100644
index 9fbe923..0000000
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * based on board-mx51_babbage.c which is
- * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/i2c-gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/can/platform/mcp251x.h>
-
-#include <mach/eukrea-baseboards.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define USBH1_RST		IMX_GPIO_NR(2, 28)
-#define ETH_RST			IMX_GPIO_NR(2, 31)
-#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 12)
-#define CAN_IRQGPIO		IMX_GPIO_NR(1, 1)
-#define CAN_RST			IMX_GPIO_NR(4, 15)
-#define CAN_NCS			IMX_GPIO_NR(4, 24)
-#define CAN_RXOBF		IMX_GPIO_NR(1, 4)
-#define CAN_RX1BF		IMX_GPIO_NR(1, 6)
-#define CAN_TXORTS		IMX_GPIO_NR(1, 7)
-#define CAN_TX1RTS		IMX_GPIO_NR(1, 8)
-#define CAN_TX2RTS		IMX_GPIO_NR(1, 9)
-#define I2C_SCL			IMX_GPIO_NR(4, 16)
-#define I2C_SDA			IMX_GPIO_NR(4, 17)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET		0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN	(1 << 25)
-
-#define	MX51_USB_PLLDIV_12_MHZ		0x00
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-#define	MX51_USB_PLL_DIV_24_MHZ		0x02
-
-static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-	MX51_PAD_USBH1_STP__USBH1_STP,
-	MX51_PAD_EIM_CS3__GPIO2_28,		/* PHY nRESET */
-
-	/* FEC */
-	MX51_PAD_EIM_DTACK__GPIO2_31,		/* PHY nRESET */
-
-	/* HSI2C */
-	MX51_PAD_I2C1_CLK__GPIO4_16,
-	MX51_PAD_I2C1_DAT__GPIO4_17,
-
-	/* CAN */
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,		/* nCS */
-	MX51_PAD_CSI2_PIXCLK__GPIO4_15,		/* nReset */
-	MX51_PAD_GPIO1_1__GPIO1_1,		/* IRQ */
-	MX51_PAD_GPIO1_4__GPIO1_4,		/* Control signals */
-	MX51_PAD_GPIO1_6__GPIO1_6,
-	MX51_PAD_GPIO1_7__GPIO1_7,
-	MX51_PAD_GPIO1_8__GPIO1_8,
-	MX51_PAD_GPIO1_9__GPIO1_9,
-
-	/* Touchscreen */
-	/* IRQ */
-	NEW_PAD_CTRL(MX51_PAD_GPIO_NAND__GPIO_NAND, PAD_CTL_PUS_22K_UP |
-			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct tsc2007_platform_data tsc2007_info = {
-	.model			= 2007,
-	.x_plate_ohms		= 180,
-};
-
-static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("pcf8563", 0x51),
-	}, {
-		I2C_BOARD_INFO("tsc2007", 0x49),
-		.type		= "tsc2007",
-		.platform_data	= &tsc2007_info,
-		.irq		= IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
-	},
-};
-
-static const struct mxc_nand_platform_data
-		eukrea_cpuimx51sd_nand_board_info __initconst = {
-	.width		= 1,
-	.hw_ecc		= 1,
-	.flash_bbt	= 1,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* The clock for the USBH1 ULPI port will come from the PHY. */
-	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
-			usbother_base + MX51_USB_CTRL_1_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-			MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init		= initialize_otg_port,
-	.portsc	= MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-	.init		= initialize_usbh1_port,
-	.portsc	= MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init eukrea_cpuimx51sd_otg_mode(char *options)
-{
-	if (!strcmp(options, "host"))
-		otg_mode_host = 1;
-	else if (!strcmp(options, "device"))
-		otg_mode_host = 0;
-	else
-		pr_info("otg_mode neither \"host\" nor \"device\". "
-			"Defaulting to device\n");
-	return 0;
-}
-__setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
-
-static struct i2c_gpio_platform_data pdata = {
-	.sda_pin		= I2C_SDA,
-	.sda_is_open_drain	= 0,
-	.scl_pin		= I2C_SCL,
-	.scl_is_open_drain	= 0,
-	.udelay			= 2,
-};
-
-static struct platform_device hsi2c_gpio_device = {
-	.name			= "i2c-gpio",
-	.id			= 0,
-	.dev.platform_data	= &pdata,
-};
-
-static struct mcp251x_platform_data mcp251x_info = {
-	.oscillator_frequency = 24E6,
-};
-
-static struct spi_board_info cpuimx51sd_spi_device[] = {
-	{
-		.modalias        = "mcp2515",
-		.max_speed_hz    = 10000000,
-		.bus_num         = 0,
-		.mode		= SPI_MODE_0,
-		.chip_select     = 0,
-		.platform_data   = &mcp251x_info,
-		.irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
-	},
-};
-
-static int cpuimx51sd_spi1_cs[] = {
-	CAN_NCS,
-};
-
-static const struct spi_imx_master cpuimx51sd_ecspi1_pdata __initconst = {
-	.chipselect	= cpuimx51sd_spi1_cs,
-	.num_chipselect	= ARRAY_SIZE(cpuimx51sd_spi1_cs),
-};
-
-static struct platform_device *platform_devices[] __initdata = {
-	&hsi2c_gpio_device,
-};
-
-static void __init eukrea_cpuimx51sd_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
-					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
-
-	gpio_request(ETH_RST, "eth_rst");
-	gpio_set_value(ETH_RST, 1);
-	imx51_add_fec(NULL);
-
-	gpio_request(CAN_IRQGPIO, "can_irq");
-	gpio_direction_input(CAN_IRQGPIO);
-	gpio_free(CAN_IRQGPIO);
-	gpio_request(CAN_NCS, "can_ncs");
-	gpio_direction_output(CAN_NCS, 1);
-	gpio_free(CAN_NCS);
-	gpio_request(CAN_RST, "can_rst");
-	gpio_direction_output(CAN_RST, 0);
-	msleep(20);
-	gpio_set_value(CAN_RST, 1);
-	imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
-	spi_register_board_info(cpuimx51sd_spi_device,
-				ARRAY_SIZE(cpuimx51sd_spi_device));
-
-	gpio_request(TSC2007_IRQGPIO, "tsc2007_irq");
-	gpio_direction_input(TSC2007_IRQGPIO);
-	gpio_free(TSC2007_IRQGPIO);
-
-	i2c_register_board_info(0, eukrea_cpuimx51sd_i2c_devices,
-			ARRAY_SIZE(eukrea_cpuimx51sd_i2c_devices));
-	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-
-	if (otg_mode_host)
-		imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	else {
-		initialize_otg_port(NULL);
-		imx51_add_fsl_usb2_udc(&usb_pdata);
-	}
-
-	gpio_request(USBH1_RST, "usb_rst");
-	gpio_direction_output(USBH1_RST, 0);
-	msleep(20);
-	gpio_set_value(USBH1_RST, 1);
-	imx51_add_mxc_ehci_hs(1, &usbh1_config);
-
-#ifdef CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD
-	eukrea_mbimxsd51_baseboard_init();
-#endif
-}
-
-static void __init eukrea_cpuimx51sd_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mxc_timer = {
-	.init	= eukrea_cpuimx51sd_timer_init,
-};
-
-MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
-	/* Maintainer: Eric Bénard <eric@eukrea.com> */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mxc_timer,
-	.init_machine = eukrea_cpuimx51sd_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
deleted file mode 100644
index 42b66e8..0000000
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx50.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx50.h"
-
-#define FEC_EN		IMX_GPIO_NR(6, 23)
-#define FEC_RESET_B	IMX_GPIO_NR(4, 12)
-
-static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
-	/* SD1 */
-	MX50_PAD_ECSPI2_SS0__GPIO_4_19,
-	MX50_PAD_EIM_CRE__GPIO_1_27,
-	MX50_PAD_SD1_CMD__SD1_CMD,
-
-	MX50_PAD_SD1_CLK__SD1_CLK,
-	MX50_PAD_SD1_D0__SD1_D0,
-	MX50_PAD_SD1_D1__SD1_D1,
-	MX50_PAD_SD1_D2__SD1_D2,
-	MX50_PAD_SD1_D3__SD1_D3,
-
-	/* SD2 */
-	MX50_PAD_SD2_CD__GPIO_5_17,
-	MX50_PAD_SD2_WP__GPIO_5_16,
-	MX50_PAD_SD2_CMD__SD2_CMD,
-	MX50_PAD_SD2_CLK__SD2_CLK,
-	MX50_PAD_SD2_D0__SD2_D0,
-	MX50_PAD_SD2_D1__SD2_D1,
-	MX50_PAD_SD2_D2__SD2_D2,
-	MX50_PAD_SD2_D3__SD2_D3,
-	MX50_PAD_SD2_D4__SD2_D4,
-	MX50_PAD_SD2_D5__SD2_D5,
-	MX50_PAD_SD2_D6__SD2_D6,
-	MX50_PAD_SD2_D7__SD2_D7,
-
-	/* SD3 */
-	MX50_PAD_SD3_CMD__SD3_CMD,
-	MX50_PAD_SD3_CLK__SD3_CLK,
-	MX50_PAD_SD3_D0__SD3_D0,
-	MX50_PAD_SD3_D1__SD3_D1,
-	MX50_PAD_SD3_D2__SD3_D2,
-	MX50_PAD_SD3_D3__SD3_D3,
-	MX50_PAD_SD3_D4__SD3_D4,
-	MX50_PAD_SD3_D5__SD3_D5,
-	MX50_PAD_SD3_D6__SD3_D6,
-	MX50_PAD_SD3_D7__SD3_D7,
-
-	/* PWR_INT */
-	MX50_PAD_ECSPI2_MISO__GPIO_4_18,
-
-	/* UART pad setting */
-	MX50_PAD_UART1_TXD__UART1_TXD,
-	MX50_PAD_UART1_RXD__UART1_RXD,
-	MX50_PAD_UART1_RTS__UART1_RTS,
-	MX50_PAD_UART2_TXD__UART2_TXD,
-	MX50_PAD_UART2_RXD__UART2_RXD,
-	MX50_PAD_UART2_CTS__UART2_CTS,
-	MX50_PAD_UART2_RTS__UART2_RTS,
-
-	MX50_PAD_I2C1_SCL__I2C1_SCL,
-	MX50_PAD_I2C1_SDA__I2C1_SDA,
-	MX50_PAD_I2C2_SCL__I2C2_SCL,
-	MX50_PAD_I2C2_SDA__I2C2_SDA,
-
-	MX50_PAD_EPITO__USBH1_PWR,
-	/* Need to comment below line if
-	 * one needs to debug owire.
-	 */
-	MX50_PAD_OWIRE__USBH1_OC,
-	/* using gpio to control otg pwr */
-	MX50_PAD_PWM2__GPIO_6_25,
-	MX50_PAD_I2C3_SCL__USBOTG_OC,
-
-	MX50_PAD_SSI_RXC__FEC_MDIO,
-	MX50_PAD_SSI_RXFS__FEC_MDC,
-	MX50_PAD_DISP_D0__FEC_TXCLK,
-	MX50_PAD_DISP_D1__FEC_RX_ER,
-	MX50_PAD_DISP_D2__FEC_RX_DV,
-	MX50_PAD_DISP_D3__FEC_RXD1,
-	MX50_PAD_DISP_D4__FEC_RXD0,
-	MX50_PAD_DISP_D5__FEC_TX_EN,
-	MX50_PAD_DISP_D6__FEC_TXD1,
-	MX50_PAD_DISP_D7__FEC_TXD0,
-	MX50_PAD_I2C3_SDA__GPIO_6_23,
-	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
-
-	MX50_PAD_CSPI_SS0__CSPI_SS0,
-	MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
-	MX50_PAD_CSPI_MOSI__CSPI_MOSI,
-	MX50_PAD_CSPI_MISO__CSPI_MISO,
-
-	/* SGTL500_OSC_EN */
-	MX50_PAD_UART1_CTS__GPIO_6_8,
-
-	/* SGTL_AMP_SHDN */
-	MX50_PAD_UART3_RXD__GPIO_6_15,
-
-	/* Keypad */
-	MX50_PAD_KEY_COL0__KEY_COL0,
-	MX50_PAD_KEY_ROW0__KEY_ROW0,
-	MX50_PAD_KEY_COL1__KEY_COL1,
-	MX50_PAD_KEY_ROW1__KEY_ROW1,
-	MX50_PAD_KEY_COL2__KEY_COL2,
-	MX50_PAD_KEY_ROW2__KEY_ROW2,
-	MX50_PAD_KEY_COL3__KEY_COL3,
-	MX50_PAD_KEY_ROW3__KEY_ROW3,
-	MX50_PAD_EIM_DA0__KEY_COL4,
-	MX50_PAD_EIM_DA1__KEY_ROW4,
-	MX50_PAD_EIM_DA2__KEY_COL5,
-	MX50_PAD_EIM_DA3__KEY_ROW5,
-	MX50_PAD_EIM_DA4__KEY_COL6,
-	MX50_PAD_EIM_DA5__KEY_ROW6,
-	MX50_PAD_EIM_DA6__KEY_COL7,
-	MX50_PAD_EIM_DA7__KEY_ROW7,
-	/*EIM pads */
-	MX50_PAD_EIM_DA8__GPIO_1_8,
-	MX50_PAD_EIM_DA9__GPIO_1_9,
-	MX50_PAD_EIM_DA10__GPIO_1_10,
-	MX50_PAD_EIM_DA11__GPIO_1_11,
-	MX50_PAD_EIM_DA12__GPIO_1_12,
-	MX50_PAD_EIM_DA13__GPIO_1_13,
-	MX50_PAD_EIM_DA14__GPIO_1_14,
-	MX50_PAD_EIM_DA15__GPIO_1_15,
-	MX50_PAD_EIM_CS2__GPIO_1_16,
-	MX50_PAD_EIM_CS1__GPIO_1_17,
-	MX50_PAD_EIM_CS0__GPIO_1_18,
-	MX50_PAD_EIM_EB0__GPIO_1_19,
-	MX50_PAD_EIM_EB1__GPIO_1_20,
-	MX50_PAD_EIM_WAIT__GPIO_1_21,
-	MX50_PAD_EIM_BCLK__GPIO_1_22,
-	MX50_PAD_EIM_RDY__GPIO_1_23,
-	MX50_PAD_EIM_OE__GPIO_1_24,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct fec_platform_data fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static inline void mx50_rdp_fec_reset(void)
-{
-	gpio_request(FEC_EN, "fec-en");
-	gpio_direction_output(FEC_EN, 0);
-	gpio_request(FEC_RESET_B, "fec-reset_b");
-	gpio_direction_output(FEC_RESET_B, 0);
-	msleep(1);
-	gpio_set_value(FEC_RESET_B, 1);
-}
-
-static const struct imxi2c_platform_data i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx50_rdp_board_init(void)
-{
-	imx50_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
-					ARRAY_SIZE(mx50_rdp_pads));
-
-	imx50_add_imx_uart(0, &uart_pdata);
-	imx50_add_imx_uart(1, &uart_pdata);
-	mx50_rdp_fec_reset();
-	imx50_add_fec(&fec_data);
-	imx50_add_imx_i2c(0, &i2c_data);
-	imx50_add_imx_i2c(1, &i2c_data);
-	imx50_add_imx_i2c(2, &i2c_data);
-}
-
-static void __init mx50_rdp_timer_init(void)
-{
-	mx50_clocks_init(32768, 24000000, 22579200);
-}
-
-static struct sys_timer mx50_rdp_timer = {
-	.init	= mx50_rdp_timer_init,
-};
-
-MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
-	.map_io = mx50_map_io,
-	.init_early = imx50_init_early,
-	.init_irq = mx50_init_irq,
-	.handle_irq = imx50_handle_irq,
-	.timer = &mx50_rdp_timer,
-	.init_machine = mx50_rdp_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
deleted file mode 100644
index 83eab41..0000000
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/3ds_debugboard.h>
-
-#include "devices-imx51.h"
-
-#define EXPIO_PARENT_INT	gpio_to_irq(IMX_GPIO_NR(1, 6))
-#define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
-
-static iomux_v3_cfg_t mx51_3ds_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-	MX51_PAD_EIM_D25__UART2_CTS,
-	MX51_PAD_EIM_D26__UART2_RTS,
-
-	/* UART3 */
-	MX51_PAD_UART3_RXD__UART3_RXD,
-	MX51_PAD_UART3_TXD__UART3_TXD,
-	MX51_PAD_EIM_D24__UART3_CTS,
-	MX51_PAD_EIM_D27__UART3_RTS,
-
-	/* CPLD PARENT IRQ PIN */
-	MX51_PAD_GPIO1_6__GPIO1_6,
-
-	/* KPP */
-	MX51_PAD_KEY_ROW0__KEY_ROW0,
-	MX51_PAD_KEY_ROW1__KEY_ROW1,
-	MX51_PAD_KEY_ROW2__KEY_ROW2,
-	MX51_PAD_KEY_ROW3__KEY_ROW3,
-	MX51_PAD_KEY_COL0__KEY_COL0,
-	MX51_PAD_KEY_COL1__KEY_COL1,
-	MX51_PAD_KEY_COL2__KEY_COL2,
-	MX51_PAD_KEY_COL3__KEY_COL3,
-	MX51_PAD_KEY_COL4__KEY_COL4,
-	MX51_PAD_KEY_COL5__KEY_COL5,
-
-	/* eCSPI2 */
-	MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
-	MX51_PAD_NANDF_RB3__ECSPI2_MISO,
-	MX51_PAD_NANDF_D15__ECSPI2_MOSI,
-	MX51_PAD_NANDF_D12__GPIO3_28,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mx51_3ds_board_keymap[] = {
-	KEY(0, 0, KEY_1),
-	KEY(0, 1, KEY_2),
-	KEY(0, 2, KEY_3),
-	KEY(0, 3, KEY_F1),
-	KEY(0, 4, KEY_UP),
-	KEY(0, 5, KEY_F2),
-
-	KEY(1, 0, KEY_4),
-	KEY(1, 1, KEY_5),
-	KEY(1, 2, KEY_6),
-	KEY(1, 3, KEY_LEFT),
-	KEY(1, 4, KEY_SELECT),
-	KEY(1, 5, KEY_RIGHT),
-
-	KEY(2, 0, KEY_7),
-	KEY(2, 1, KEY_8),
-	KEY(2, 2, KEY_9),
-	KEY(2, 3, KEY_F3),
-	KEY(2, 4, KEY_DOWN),
-	KEY(2, 5, KEY_F4),
-
-	KEY(3, 0, KEY_0),
-	KEY(3, 1, KEY_OK),
-	KEY(3, 2, KEY_ESC),
-	KEY(3, 3, KEY_ENTER),
-	KEY(3, 4, KEY_MENU),
-	KEY(3, 5, KEY_BACK)
-};
-
-static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
-	.keymap		= mx51_3ds_board_keymap,
-	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
-};
-
-static int mx51_3ds_spi2_cs[] = {
-	MXC_SPI_CS(0),
-	MX51_3DS_ECSPI2_CS,
-};
-
-static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
-	.chipselect	= mx51_3ds_spi2_cs,
-	.num_chipselect	= ARRAY_SIZE(mx51_3ds_spi2_cs),
-};
-
-static struct spi_board_info mx51_3ds_spi_nor_device[] = {
-	{
-	 .modalias = "m25p80",
-	 .max_speed_hz = 25000000,	/* max spi clock (SCK) speed in HZ */
-	 .bus_num = 1,
-	 .chip_select = 1,
-	 .mode = SPI_MODE_0,
-	 .platform_data = NULL,},
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_3ds_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
-					ARRAY_SIZE(mx51_3ds_pads));
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
-	spi_register_board_info(mx51_3ds_spi_nor_device,
-				ARRAY_SIZE(mx51_3ds_spi_nor_device));
-
-	if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
-		printk(KERN_WARNING "Init of the debugboard failed, all "
-				    "devices on the board are unusable.\n");
-
-	imx51_add_sdhci_esdhc_imx(0, NULL);
-	imx51_add_imx_keypad(&mx51_3ds_map_data);
-	imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_3ds_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_3ds_timer = {
-	.init = mx51_3ds_timer_init,
-};
-
-MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_3ds_timer,
-	.init_machine = mx51_3ds_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
deleted file mode 100644
index e4b822e..0000000
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "cpu_op-mx51.h"
-
-#define BABBAGE_USB_HUB_RESET	IMX_GPIO_NR(1, 7)
-#define BABBAGE_USBH1_STP	IMX_GPIO_NR(1, 27)
-#define BABBAGE_USB_PHY_RESET	IMX_GPIO_NR(2, 5)
-#define BABBAGE_FEC_PHY_RESET	IMX_GPIO_NR(2, 14)
-#define BABBAGE_POWER_KEY	IMX_GPIO_NR(2, 21)
-#define BABBAGE_ECSPI1_CS0	IMX_GPIO_NR(4, 24)
-#define BABBAGE_ECSPI1_CS1	IMX_GPIO_NR(4, 25)
-#define BABBAGE_SD2_CD		IMX_GPIO_NR(1, 6)
-#define BABBAGE_SD2_WP		IMX_GPIO_NR(1, 5)
-
-/* USB_CTRL_1 */
-#define MX51_USB_CTRL_1_OFFSET			0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN		(1 << 25)
-
-#define	MX51_USB_PLLDIV_12_MHZ		0x00
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-#define	MX51_USB_PLL_DIV_24_MHZ	0x02
-
-static struct gpio_keys_button babbage_buttons[] = {
-	{
-		.gpio		= BABBAGE_POWER_KEY,
-		.code		= BTN_0,
-		.desc		= "PWR",
-		.active_low	= 1,
-		.wakeup		= 1,
-	},
-};
-
-static const struct gpio_keys_platform_data imx_button_data __initconst = {
-	.buttons	= babbage_buttons,
-	.nbuttons	= ARRAY_SIZE(babbage_buttons),
-};
-
-static iomux_v3_cfg_t mx51babbage_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-
-	/* UART3 */
-	MX51_PAD_EIM_D25__UART3_RXD,
-	MX51_PAD_EIM_D26__UART3_TXD,
-	MX51_PAD_EIM_D27__UART3_RTS,
-	MX51_PAD_EIM_D24__UART3_CTS,
-
-	/* I2C1 */
-	MX51_PAD_EIM_D16__I2C1_SDA,
-	MX51_PAD_EIM_D19__I2C1_SCL,
-
-	/* I2C2 */
-	MX51_PAD_KEY_COL4__I2C2_SCL,
-	MX51_PAD_KEY_COL5__I2C2_SDA,
-
-	/* HSI2C */
-	MX51_PAD_I2C1_CLK__I2C1_CLK,
-	MX51_PAD_I2C1_DAT__I2C1_DAT,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-	/* USB HUB reset line*/
-	MX51_PAD_GPIO1_7__GPIO1_7,
-
-	/* USB PHY reset line */
-	MX51_PAD_EIM_D21__GPIO2_5,
-
-	/* FEC */
-	MX51_PAD_EIM_EB2__FEC_MDIO,
-	MX51_PAD_EIM_EB3__FEC_RDATA1,
-	MX51_PAD_EIM_CS2__FEC_RDATA2,
-	MX51_PAD_EIM_CS3__FEC_RDATA3,
-	MX51_PAD_EIM_CS4__FEC_RX_ER,
-	MX51_PAD_EIM_CS5__FEC_CRS,
-	MX51_PAD_NANDF_RB2__FEC_COL,
-	MX51_PAD_NANDF_RB3__FEC_RX_CLK,
-	MX51_PAD_NANDF_D9__FEC_RDATA0,
-	MX51_PAD_NANDF_D8__FEC_TDATA0,
-	MX51_PAD_NANDF_CS2__FEC_TX_ER,
-	MX51_PAD_NANDF_CS3__FEC_MDC,
-	MX51_PAD_NANDF_CS4__FEC_TDATA1,
-	MX51_PAD_NANDF_CS5__FEC_TDATA2,
-	MX51_PAD_NANDF_CS6__FEC_TDATA3,
-	MX51_PAD_NANDF_CS7__FEC_TX_EN,
-	MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK,
-
-	/* FEC PHY reset line */
-	MX51_PAD_EIM_A20__GPIO2_14,
-
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	/* CD/WP from controller */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-	/* CD/WP gpio */
-	MX51_PAD_GPIO1_6__GPIO1_6,
-	MX51_PAD_GPIO1_5__GPIO1_5,
-
-	/* eCSPI1 */
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static const struct imxi2c_platform_data babbage_hsi2c_data __initconst = {
-	.bitrate = 400000,
-};
-
-static struct gpio mx51_babbage_usbh1_gpios[] = {
-	{ BABBAGE_USBH1_STP, GPIOF_OUT_INIT_LOW, "usbh1_stp" },
-	{ BABBAGE_USB_PHY_RESET, GPIOF_OUT_INIT_LOW, "usbh1_phy_reset" },
-};
-
-static int gpio_usbh1_active(void)
-{
-	iomux_v3_cfg_t usbh1stp_gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-	int ret;
-
-	/* Set USBH1_STP to GPIO and toggle it */
-	mxc_iomux_v3_setup_pad(usbh1stp_gpio);
-	ret = gpio_request_array(mx51_babbage_usbh1_gpios,
-					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-
-	if (ret) {
-		pr_debug("failed to get USBH1 pins: %d\n", ret);
-		return ret;
-	}
-
-	msleep(100);
-	gpio_set_value(BABBAGE_USBH1_STP, 1);
-	gpio_set_value(BABBAGE_USB_PHY_RESET, 1);
-	gpio_free_array(mx51_babbage_usbh1_gpios,
-					ARRAY_SIZE(mx51_babbage_usbh1_gpios));
-	return 0;
-}
-
-static inline void babbage_usbhub_reset(void)
-{
-	int ret;
-
-	/* Reset USB hub */
-	ret = gpio_request_one(BABBAGE_USB_HUB_RESET,
-					GPIOF_OUT_INIT_LOW, "GPIO1_7");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_USB_HUB_RESET: %d\n", ret);
-		return;
-	}
-
-	msleep(2);
-	/* Deassert reset */
-	gpio_set_value(BABBAGE_USB_HUB_RESET, 1);
-}
-
-static inline void babbage_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
-					GPIOF_OUT_INIT_LOW, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	msleep(1);
-	gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
-}
-
-/* This function is board specific as the bit mask for the plldiv will also
-be different for other Freescale SoCs, thus a common bitmask is not
-possible and cannot get place in /plat-mxc/ehci.c.*/
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
-}
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	/* The clock for the USBH1 ULPI port will come externally from the PHY. */
-	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
-			MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init		= initialize_otg_port,
-	.portsc	= MXC_EHCI_UTMI_16BIT,
-};
-
-static const struct fsl_usb2_platform_data usb_pdata __initconst = {
-	.operating_mode	= FSL_USB2_DR_DEVICE,
-	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
-};
-
-static const struct mxc_usbh_platform_data usbh1_config __initconst = {
-	.init		= initialize_usbh1_port,
-	.portsc	= MXC_EHCI_MODE_ULPI,
-};
-
-static int otg_mode_host;
-
-static int __init babbage_otg_mode(char *options)
-{
-	if (!strcmp(options, "host"))
-		otg_mode_host = 1;
-	else if (!strcmp(options, "device"))
-		otg_mode_host = 0;
-	else
-		pr_info("otg_mode neither \"host\" nor \"device\". "
-			"Defaulting to device\n");
-	return 0;
-}
-__setup("otg_mode=", babbage_otg_mode);
-
-static struct spi_board_info mx51_babbage_spi_board_info[] __initdata = {
-	{
-		.modalias = "mtd_dataflash",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.mode = SPI_MODE_0,
-		.platform_data = NULL,
-	},
-};
-
-static int mx51_babbage_spi_cs[] = {
-	BABBAGE_ECSPI1_CS0,
-	BABBAGE_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
-	.chipselect     = mx51_babbage_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_babbage_spi_cs),
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd1_data __initconst = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static const struct esdhc_platform_data mx51_babbage_sd2_data __initconst = {
-	.cd_gpio = BABBAGE_SD2_CD,
-	.wp_gpio = BABBAGE_SD2_WP,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_GPIO,
-};
-
-void __init imx51_babbage_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
-					 ARRAY_SIZE(mx51babbage_pads));
-}
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_babbage_init(void)
-{
-	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t power_key = NEW_PAD_CTRL(MX51_PAD_EIM_A27__GPIO2_21,
-		PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH);
-
-	imx51_soc_init();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
-	imx51_babbage_common_init();
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, NULL);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	babbage_fec_reset();
-	imx51_add_fec(NULL);
-
-	/* Set the PAD settings for the pwr key. */
-	mxc_iomux_v3_setup_pad(power_key);
-	imx_add_gpio_keys(&imx_button_data);
-
-	imx51_add_imx_i2c(0, &babbage_i2c_data);
-	imx51_add_imx_i2c(1, &babbage_i2c_data);
-	imx51_add_hsi2c(&babbage_hsi2c_data);
-
-	if (otg_mode_host)
-		imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	else {
-		initialize_otg_port(NULL);
-		imx51_add_fsl_usb2_udc(&usb_pdata);
-	}
-
-	gpio_usbh1_active();
-	imx51_add_mxc_ehci_hs(1, &usbh1_config);
-	/* setback USBH1_STP to be function */
-	mxc_iomux_v3_setup_pad(usbh1stp);
-	babbage_usbhub_reset();
-
-	imx51_add_sdhci_esdhc_imx(0, &mx51_babbage_sd1_data);
-	imx51_add_sdhci_esdhc_imx(1, &mx51_babbage_sd2_data);
-
-	spi_register_board_info(mx51_babbage_spi_board_info,
-		ARRAY_SIZE(mx51_babbage_spi_board_info));
-	imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
-	imx51_add_imx2_wdt(0, NULL);
-}
-
-static void __init mx51_babbage_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_babbage_timer = {
-	.init = mx51_babbage_timer_init,
-};
-
-MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
-	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_babbage_timer,
-	.init_machine = mx51_babbage_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
deleted file mode 100644
index 3a5ed2d..0000000
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2010 Linaro Limited
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
-#define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
-#define EFIKAMX_PCBID2		IMX_GPIO_NR(3, 11)
-
-#define EFIKAMX_BLUE_LED	IMX_GPIO_NR(3, 13)
-#define EFIKAMX_GREEN_LED	IMX_GPIO_NR(3, 14)
-#define EFIKAMX_RED_LED		IMX_GPIO_NR(3, 15)
-
-#define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
-
-/* board 1.1 doesn't have same reset gpio */
-#define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
-#define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
-
-#define EFIKAMX_POWEROFF	IMX_GPIO_NR(4, 13)
-
-#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
-
-/* the pci ids pin have pull up. they're driven low according to board id */
-#define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID2	IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-
-static iomux_v3_cfg_t mx51efikamx_pads[] = {
-	/* board id */
-	MX51_PAD_PCBID0,
-	MX51_PAD_PCBID1,
-	MX51_PAD_PCBID2,
-
-	/* leds */
-	MX51_PAD_CSI1_D9__GPIO3_13,
-	MX51_PAD_CSI1_VSYNC__GPIO3_14,
-	MX51_PAD_CSI1_HSYNC__GPIO3_15,
-
-	/* power key */
-	MX51_PAD_PWRKEY,
-
-	/* reset */
-	MX51_PAD_DI1_PIN13__GPIO3_2,
-	MX51_PAD_GPIO1_4__GPIO1_4,
-
-	/* power off */
-	MX51_PAD_CSI2_VSYNC__GPIO4_13,
-};
-
-/*   PCBID2  PCBID1 PCBID0  STATE
-	1       1      1    ER1:rev1.1
-	1       1      0    ER2:rev1.2
-	1       0      1    ER3:rev1.3
-	1       0      0    ER4:rev1.4
-*/
-static void __init mx51_efikamx_board_id(void)
-{
-	int id;
-
-	/* things are taking time to settle */
-	msleep(150);
-
-	gpio_request(EFIKAMX_PCBID0, "pcbid0");
-	gpio_direction_input(EFIKAMX_PCBID0);
-	gpio_request(EFIKAMX_PCBID1, "pcbid1");
-	gpio_direction_input(EFIKAMX_PCBID1);
-	gpio_request(EFIKAMX_PCBID2, "pcbid2");
-	gpio_direction_input(EFIKAMX_PCBID2);
-
-	id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
-	id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
-	id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
-
-	switch (id) {
-	case 7:
-		system_rev = 0x11;
-		break;
-	case 6:
-		system_rev = 0x12;
-		break;
-	case 5:
-		system_rev = 0x13;
-		break;
-	case 4:
-		system_rev = 0x14;
-		break;
-	default:
-		system_rev = 0x10;
-		break;
-	}
-
-	if ((system_rev == 0x10)
-		|| (system_rev == 0x12)
-		|| (system_rev == 0x14)) {
-		printk(KERN_WARNING
-			"EfikaMX: Unsupported board revision 1.%u!\n",
-			system_rev & 0xf);
-	}
-}
-
-static struct gpio_led mx51_efikamx_leds[] __initdata = {
-	{
-		.name = "efikamx:green",
-		.default_trigger = "default-on",
-		.gpio = EFIKAMX_GREEN_LED,
-	},
-	{
-		.name = "efikamx:red",
-		.default_trigger = "ide-disk",
-		.gpio = EFIKAMX_RED_LED,
-	},
-	{
-		.name = "efikamx:blue",
-		.default_trigger = "mmc0",
-		.gpio = EFIKAMX_BLUE_LED,
-	},
-};
-
-static const struct gpio_led_platform_data
-		mx51_efikamx_leds_data __initconst = {
-	.leds = mx51_efikamx_leds,
-	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
-};
-
-static struct esdhc_platform_data sd_pdata = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct gpio_keys_button mx51_efikamx_powerkey[] = {
-	{
-		.code = KEY_POWER,
-		.gpio = EFIKAMX_POWER_KEY,
-		.type = EV_PWR,
-		.desc = "Power Button (CM)",
-		.wakeup = 1,
-		.debounce_interval = 10, /* ms */
-	},
-};
-
-static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
-	.buttons = mx51_efikamx_powerkey,
-	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
-};
-
-static void mx51_efikamx_restart(char mode, const char *cmd)
-{
-	if (system_rev == 0x11)
-		gpio_direction_output(EFIKAMX_RESET1_1, 0);
-	else
-		gpio_direction_output(EFIKAMX_RESET, 0);
-}
-
-static struct regulator *pwgt1, *pwgt2, *coincell;
-
-static void mx51_efikamx_power_off(void)
-{
-	if (!IS_ERR(coincell))
-		regulator_disable(coincell);
-
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_disable(pwgt2);
-		regulator_disable(pwgt1);
-	}
-	gpio_direction_output(EFIKAMX_POWEROFF, 1);
-}
-
-static int __init mx51_efikamx_power_init(void)
-{
-	if (machine_is_mx51_efikamx()) {
-		pwgt1 = regulator_get(NULL, "pwgt1");
-		pwgt2 = regulator_get(NULL, "pwgt2");
-		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-			regulator_enable(pwgt1);
-			regulator_enable(pwgt2);
-		}
-		gpio_request(EFIKAMX_POWEROFF, "poweroff");
-		pm_power_off = mx51_efikamx_power_off;
-
-		/* enable coincell charger. maybe need a small power driver ? */
-		coincell = regulator_get(NULL, "coincell");
-		if (!IS_ERR(coincell)) {
-			regulator_set_voltage(coincell, 3000000, 3000000);
-			regulator_enable(coincell);
-		}
-
-		regulator_has_full_constraints();
-	}
-
-	return 0;
-}
-late_initcall(mx51_efikamx_power_init);
-
-static void __init mx51_efikamx_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
-					ARRAY_SIZE(mx51efikamx_pads));
-	efika_board_common_init();
-
-	mx51_efikamx_board_id();
-
-	/* on < 1.2 boards both SD controllers are used */
-	if (system_rev < 0x12) {
-		imx51_add_sdhci_esdhc_imx(0, NULL);
-		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
-		mx51_efikamx_leds[2].default_trigger = "mmc1";
-	} else
-		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
-
-	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
-	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
-
-	if (system_rev == 0x11) {
-		gpio_request(EFIKAMX_RESET1_1, "reset");
-		gpio_direction_output(EFIKAMX_RESET1_1, 1);
-	} else {
-		gpio_request(EFIKAMX_RESET, "reset");
-		gpio_direction_output(EFIKAMX_RESET, 1);
-	}
-
-	/*
-	 * enable wifi by default only on mx
-	 * sb and mx have same wlan pin but the value to enable it are
-	 * different :/
-	 */
-	gpio_request(EFIKA_WLAN_EN, "wlan_en");
-	gpio_direction_output(EFIKA_WLAN_EN, 0);
-	msleep(10);
-
-	gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
-	gpio_direction_output(EFIKA_WLAN_RESET, 0);
-	msleep(10);
-	gpio_set_value(EFIKA_WLAN_RESET, 1);
-}
-
-static void __init mx51_efikamx_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikamx_timer = {
-	.init = mx51_efikamx_timer_init,
-};
-
-MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
-	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_efikamx_timer,
-	.init_machine = mx51_efikamx_init,
-	.restart = mx51_efikamx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
deleted file mode 100644
index ea5f65b..0000000
--- a/arch/arm/mach-mx5/board-mx51_efikasb.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
-#define EFIKASB_GREEN_LED	IMX_GPIO_NR(1, 3)
-#define EFIKASB_WHITE_LED	IMX_GPIO_NR(2, 25)
-#define EFIKASB_PCBID0		IMX_GPIO_NR(2, 28)
-#define EFIKASB_PCBID1		IMX_GPIO_NR(2, 29)
-#define EFIKASB_PWRKEY		IMX_GPIO_NR(2, 31)
-#define EFIKASB_LID		IMX_GPIO_NR(3, 14)
-#define EFIKASB_POWEROFF	IMX_GPIO_NR(4, 13)
-#define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
-
-#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-
-static iomux_v3_cfg_t mx51efikasb_pads[] = {
-	/* USB HOST2 */
-	MX51_PAD_EIM_D16__USBH2_DATA0,
-	MX51_PAD_EIM_D17__USBH2_DATA1,
-	MX51_PAD_EIM_D18__USBH2_DATA2,
-	MX51_PAD_EIM_D19__USBH2_DATA3,
-	MX51_PAD_EIM_D20__USBH2_DATA4,
-	MX51_PAD_EIM_D21__USBH2_DATA5,
-	MX51_PAD_EIM_D22__USBH2_DATA6,
-	MX51_PAD_EIM_D23__USBH2_DATA7,
-	MX51_PAD_EIM_A24__USBH2_CLK,
-	MX51_PAD_EIM_A25__USBH2_DIR,
-	MX51_PAD_EIM_A26__USBH2_STP,
-	MX51_PAD_EIM_A27__USBH2_NXT,
-
-	/* leds */
-	MX51_PAD_EIM_CS0__GPIO2_25,
-	MX51_PAD_GPIO1_3__GPIO1_3,
-
-	/* pcb id */
-	MX51_PAD_EIM_CS3__GPIO2_28,
-	MX51_PAD_EIM_CS4__GPIO2_29,
-
-	/* lid */
-	MX51_PAD_CSI1_VSYNC__GPIO3_14,
-
-	/* power key*/
-	MX51_PAD_PWRKEY,
-
-	/* wifi/bt button */
-	MX51_PAD_DI1_PIN12__GPIO3_1,
-
-	/* power off */
-	MX51_PAD_CSI2_VSYNC__GPIO4_13,
-
-	/* wdog reset */
-	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
-
-	/* BT */
-	MX51_PAD_EIM_A17__GPIO2_11,
-
-	MX51_PAD_SD1_CD,
-};
-
-static int initialize_usbh2_port(struct platform_device *pdev)
-{
-	iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
-	iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
-
-	mxc_iomux_v3_setup_pad(usbh2gpio);
-	gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
-	gpio_direction_output(EFIKASB_USBH2_STP, 0);
-	msleep(1);
-	gpio_set_value(EFIKASB_USBH2_STP, 1);
-	msleep(1);
-
-	gpio_free(EFIKASB_USBH2_STP);
-	mxc_iomux_v3_setup_pad(usbh2stp);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh2_config __initdata = {
-	.init   = initialize_usbh2_port,
-	.portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void __init mx51_efikasb_usb(void)
-{
-	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-	if (usbh2_config.otg)
-		imx51_add_mxc_ehci_hs(2, &usbh2_config);
-}
-
-static const struct gpio_led mx51_efikasb_leds[] __initconst = {
-	{
-		.name = "efikasb:green",
-		.default_trigger = "default-on",
-		.gpio = EFIKASB_GREEN_LED,
-		.active_low = 1,
-	},
-	{
-		.name = "efikasb:white",
-		.default_trigger = "caps",
-		.gpio = EFIKASB_WHITE_LED,
-	},
-};
-
-static const struct gpio_led_platform_data
-		mx51_efikasb_leds_data __initconst = {
-	.leds = mx51_efikasb_leds,
-	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
-};
-
-static struct gpio_keys_button mx51_efikasb_keys[] = {
-	{
-		.code = KEY_POWER,
-		.gpio = EFIKASB_PWRKEY,
-		.type = EV_KEY,
-		.desc = "Power Button",
-		.wakeup = 1,
-		.active_low = 1,
-	},
-	{
-		.code = SW_LID,
-		.gpio = EFIKASB_LID,
-		.type = EV_SW,
-		.desc = "Lid Switch",
-		.active_low = 1,
-	},
-	{
-		.code = KEY_RFKILL,
-		.gpio = EFIKASB_RFKILL,
-		.type = EV_KEY,
-		.desc = "rfkill",
-		.active_low = 1,
-	},
-};
-
-static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
-	.buttons = mx51_efikasb_keys,
-	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
-};
-
-static struct esdhc_platform_data sd0_pdata = {
-#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
-	.cd_gpio = EFIKASB_SD1_CD,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct esdhc_platform_data sd1_pdata = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct regulator *pwgt1, *pwgt2;
-
-static void mx51_efikasb_power_off(void)
-{
-	gpio_set_value(EFIKA_USB_PHY_RESET, 0);
-
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_disable(pwgt2);
-		regulator_disable(pwgt1);
-	}
-	gpio_direction_output(EFIKASB_POWEROFF, 1);
-}
-
-static int __init mx51_efikasb_power_init(void)
-{
-	if (machine_is_mx51_efikasb()) {
-		pwgt1 = regulator_get(NULL, "pwgt1");
-		pwgt2 = regulator_get(NULL, "pwgt2");
-		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-			regulator_enable(pwgt1);
-			regulator_enable(pwgt2);
-		}
-		gpio_request(EFIKASB_POWEROFF, "poweroff");
-		pm_power_off = mx51_efikasb_power_off;
-
-		regulator_has_full_constraints();
-	}
-
-	return 0;
-}
-late_initcall(mx51_efikasb_power_init);
-
-/* 01     R1.3 board
-   10     R2.0 board */
-static void __init mx51_efikasb_board_id(void)
-{
-	int id;
-
-	gpio_request(EFIKASB_PCBID0, "pcb id0");
-	gpio_direction_input(EFIKASB_PCBID0);
-	gpio_request(EFIKASB_PCBID1, "pcb id1");
-	gpio_direction_input(EFIKASB_PCBID1);
-
-	id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
-	id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
-
-	switch (id) {
-	default:
-		break;
-	case 1:
-		system_rev = 0x13;
-		break;
-	case 2:
-		system_rev = 0x20;
-		break;
-	}
-}
-
-static void __init efikasb_board_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
-					ARRAY_SIZE(mx51efikasb_pads));
-	efika_board_common_init();
-
-	mx51_efikasb_board_id();
-	mx51_efikasb_usb();
-	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
-	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
-
-	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
-	imx_add_gpio_keys(&mx51_efikasb_keys_data);
-}
-
-static void __init mx51_efikasb_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikasb_timer = {
-	.init	= mx51_efikasb_timer_init,
-};
-
-MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.init_machine =  efikasb_board_init,
-	.timer = &mx51_efikasb_timer,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_ard.c b/arch/arm/mach-mx5/board-mx53_ard.c
deleted file mode 100644
index 5f224f1..0000000
--- a/arch/arm/mach-mx5/board-mx53_ard.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define ARD_ETHERNET_INT_B	IMX_GPIO_NR(2, 31)
-#define ARD_SD1_CD		IMX_GPIO_NR(1, 1)
-#define ARD_SD1_WP		IMX_GPIO_NR(1, 9)
-#define ARD_I2CPORTEXP_B	IMX_GPIO_NR(2, 3)
-#define ARD_VOLUMEDOWN		IMX_GPIO_NR(4, 0)
-#define ARD_HOME			IMX_GPIO_NR(5, 10)
-#define ARD_BACK			IMX_GPIO_NR(5, 11)
-#define ARD_PROG			IMX_GPIO_NR(5, 12)
-#define ARD_VOLUMEUP		IMX_GPIO_NR(5, 13)
-
-static iomux_v3_cfg_t mx53_ard_pads[] = {
-	/* UART1 */
-	MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
-	MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
-	/* WEIM for CS1 */
-	MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
-	MX53_PAD_EIM_D16__EMI_WEIM_D_16,
-	MX53_PAD_EIM_D17__EMI_WEIM_D_17,
-	MX53_PAD_EIM_D18__EMI_WEIM_D_18,
-	MX53_PAD_EIM_D19__EMI_WEIM_D_19,
-	MX53_PAD_EIM_D20__EMI_WEIM_D_20,
-	MX53_PAD_EIM_D21__EMI_WEIM_D_21,
-	MX53_PAD_EIM_D22__EMI_WEIM_D_22,
-	MX53_PAD_EIM_D23__EMI_WEIM_D_23,
-	MX53_PAD_EIM_D24__EMI_WEIM_D_24,
-	MX53_PAD_EIM_D25__EMI_WEIM_D_25,
-	MX53_PAD_EIM_D26__EMI_WEIM_D_26,
-	MX53_PAD_EIM_D27__EMI_WEIM_D_27,
-	MX53_PAD_EIM_D28__EMI_WEIM_D_28,
-	MX53_PAD_EIM_D29__EMI_WEIM_D_29,
-	MX53_PAD_EIM_D30__EMI_WEIM_D_30,
-	MX53_PAD_EIM_D31__EMI_WEIM_D_31,
-	MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
-	MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
-	MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
-	MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
-	MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
-	MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
-	MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
-	MX53_PAD_EIM_OE__EMI_WEIM_OE,
-	MX53_PAD_EIM_RW__EMI_WEIM_RW,
-	MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
-	/* SDHC1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
-	MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
-	MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
-	MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
-	MX53_PAD_GPIO_1__GPIO1_1,
-	MX53_PAD_GPIO_9__GPIO1_9,
-	/* I2C2 */
-	MX53_PAD_EIM_EB2__I2C2_SCL,
-	MX53_PAD_KEY_ROW3__I2C2_SDA,
-	/* I2C3 */
-	MX53_PAD_GPIO_3__I2C3_SCL,
-	MX53_PAD_GPIO_16__I2C3_SDA,
-	/* GPIO */
-	MX53_PAD_DISP0_DAT16__GPIO5_10,	/* home */
-	MX53_PAD_DISP0_DAT17__GPIO5_11,	/* back */
-	MX53_PAD_DISP0_DAT18__GPIO5_12,	/* prog */
-	MX53_PAD_DISP0_DAT19__GPIO5_13,	/* vol up */
-	MX53_PAD_GPIO_10__GPIO4_0,		/* vol down */
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
-{							\
-	.gpio		= gpio_num,				\
-	.type		= EV_KEY,				\
-	.code		= ev_code,				\
-	.active_low	= act_low,				\
-	.desc		= "btn " descr,			\
-	.wakeup		= wake,					\
-}
-
-static struct gpio_keys_button ard_buttons[] = {
-	GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
-	GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
-	GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
-	GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
-	GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data ard_button_data __initconst = {
-	.buttons        = ard_buttons,
-	.nbuttons       = ARRAY_SIZE(ard_buttons),
-};
-
-static struct resource ard_smsc911x_resources[] = {
-	{
-		.start = MX53_CS1_64MB_BASE_ADDR,
-		.end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-		.end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct smsc911x_platform_config ard_smsc911x_config = {
-	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags = SMSC911X_USE_32BIT,
-};
-
-static struct platform_device ard_smsc_lan9220_device = {
-	.name = "smsc911x",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(ard_smsc911x_resources),
-	.resource = ard_smsc911x_resources,
-	.dev = {
-		.platform_data = &ard_smsc911x_config,
-	},
-};
-
-static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
-	.cd_gpio = ARD_SD1_CD,
-	.wp_gpio = ARD_SD1_WP,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c2_data = {
-	.bitrate = 50000,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c3_data = {
-	.bitrate = 400000,
-};
-
-static void __init mx53_ard_io_init(void)
-{
-	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
-	gpio_direction_input(ARD_ETHERNET_INT_B);
-
-	gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
-	gpio_direction_output(ARD_I2CPORTEXP_B, 1);
-}
-
-/* Config CS1 settings for ethernet controller */
-static int weim_cs_config(void)
-{
-	u32 reg;
-	void __iomem *weim_base, *iomuxc_base;
-
-	weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
-	if (!weim_base)
-		return -ENOMEM;
-
-	iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
-	if (!iomuxc_base)
-		return -ENOMEM;
-
-	/* CS1 timings for LAN9220 */
-	writel(0x20001, (weim_base + 0x18));
-	writel(0x0, (weim_base + 0x1C));
-	writel(0x16000202, (weim_base + 0x20));
-	writel(0x00000002, (weim_base + 0x24));
-	writel(0x16002082, (weim_base + 0x28));
-	writel(0x00000000, (weim_base + 0x2C));
-	writel(0x00000000, (weim_base + 0x90));
-
-	/* specify 64 MB on CS1 and CS0 on GPR1 */
-	reg = readl(iomuxc_base + 0x4);
-	reg &= ~0x3F;
-	reg |= 0x1B;
-	writel(reg, (iomuxc_base + 0x4));
-
-	iounmap(iomuxc_base);
-	iounmap(weim_base);
-
-	return 0;
-}
-
-void __init imx53_ard_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-					 ARRAY_SIZE(mx53_ard_pads));
-	weim_cs_config();
-}
-
-static struct platform_device *devices[] __initdata = {
-	&ard_smsc_lan9220_device,
-};
-
-static void __init mx53_ard_board_init(void)
-{
-	imx53_soc_init();
-	imx53_add_imx_uart(0, NULL);
-
-	imx53_ard_common_init();
-	mx53_ard_io_init();
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
-	imx53_add_imx2_wdt(0, NULL);
-	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
-	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
-	imx_add_gpio_keys(&ard_button_data);
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_ard_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_ard_timer = {
-	.init	= mx53_ard_timer_init,
-};
-
-MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_ard_timer,
-	.init_machine = mx53_ard_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
deleted file mode 100644
index d6ce137..0000000
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/iomux-mx53.h>
-
-#define MX53_EVK_FEC_PHY_RST	IMX_GPIO_NR(7, 6)
-#define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
-#define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
-#define MX53EVK_LED		IMX_GPIO_NR(7, 7)
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-static iomux_v3_cfg_t mx53_evk_pads[] = {
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-	MX53_PAD_PATA_DIOR__UART2_RTS,
-	MX53_PAD_PATA_INTRQ__UART2_CTS,
-
-	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-
-	MX53_PAD_EIM_D16__ECSPI1_SCLK,
-	MX53_PAD_EIM_D17__ECSPI1_MISO,
-	MX53_PAD_EIM_D18__ECSPI1_MOSI,
-
-	/* ecspi chip select lines */
-	MX53_PAD_EIM_EB2__GPIO2_30,
-	MX53_PAD_EIM_D19__GPIO3_19,
-	/* LED */
-	MX53_PAD_PATA_DA_1__GPIO7_7,
-};
-
-static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct gpio_led mx53evk_leds[] __initconst = {
-	{
-		.name			= "green",
-		.default_trigger	= "heartbeat",
-		.gpio			= MX53EVK_LED,
-	},
-};
-
-static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
-	.leds		= mx53evk_leds,
-	.num_leds	= ARRAY_SIZE(mx53evk_leds),
-};
-
-static inline void mx53_evk_init_uart(void)
-{
-	imx53_add_imx_uart(0, NULL);
-	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
-	imx53_add_imx_uart(2, NULL);
-}
-
-static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static inline void mx53_evk_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
-							"fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	msleep(1);
-	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
-	{
-		.modalias = "mtd_dataflash",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.mode = SPI_MODE_0,
-		.platform_data = NULL,
-	},
-};
-
-static int mx53_evk_spi_cs[] = {
-	EVK_ECSPI1_CS0,
-	EVK_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx53_evk_spi_data __initconst = {
-	.chipselect     = mx53_evk_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
-};
-
-void __init imx53_evk_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-					 ARRAY_SIZE(mx53_evk_pads));
-}
-
-static void __init mx53_evk_board_init(void)
-{
-	imx53_soc_init();
-	imx53_evk_common_init();
-
-	mx53_evk_init_uart();
-	mx53_evk_fec_reset();
-	imx53_add_fec(&mx53_evk_fec_pdata);
-
-	imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
-	imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
-
-	imx53_add_sdhci_esdhc_imx(0, NULL);
-	imx53_add_sdhci_esdhc_imx(1, NULL);
-
-	spi_register_board_info(mx53_evk_spi_board_info,
-		ARRAY_SIZE(mx53_evk_spi_board_info));
-	imx53_add_ecspi(0, &mx53_evk_spi_data);
-	imx53_add_imx2_wdt(0, NULL);
-	gpio_led_register_device(-1, &mx53evk_leds_data);
-}
-
-static void __init mx53_evk_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_evk_timer = {
-	.init	= mx53_evk_timer_init,
-};
-
-MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_evk_timer,
-	.init_machine = mx53_evk_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
deleted file mode 100644
index fd8b524..0000000
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define MX53_LOCO_POWER			IMX_GPIO_NR(1, 8)
-#define MX53_LOCO_UI1			IMX_GPIO_NR(2, 14)
-#define MX53_LOCO_UI2			IMX_GPIO_NR(2, 15)
-#define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
-#define LOCO_LED			IMX_GPIO_NR(7, 7)
-#define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
-#define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
-#define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
-#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
-
-static iomux_v3_cfg_t mx53_loco_pads[] = {
-	/* FEC */
-	MX53_PAD_FEC_MDC__FEC_MDC,
-	MX53_PAD_FEC_MDIO__FEC_MDIO,
-	MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
-	MX53_PAD_FEC_RX_ER__FEC_RX_ER,
-	MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
-	MX53_PAD_FEC_RXD1__FEC_RDATA_1,
-	MX53_PAD_FEC_RXD0__FEC_RDATA_0,
-	MX53_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX53_PAD_FEC_TXD1__FEC_TDATA_1,
-	MX53_PAD_FEC_TXD0__FEC_TDATA_0,
-	/* FEC_nRST */
-	MX53_PAD_PATA_DA_0__GPIO7_6,
-	/* FEC_nINT */
-	MX53_PAD_PATA_DATA4__GPIO2_4,
-	/* AUDMUX5 */
-	MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
-	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
-	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
-	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
-	/* I2C2 */
-	MX53_PAD_KEY_COL3__I2C2_SCL,
-	MX53_PAD_KEY_ROW3__I2C2_SDA,
-	/* SD1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	/* SD1_CD */
-	MX53_PAD_EIM_DA13__GPIO3_13,
-	/* SD3 */
-	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-	/* SD3_CD */
-	MX53_PAD_EIM_DA11__GPIO3_11,
-	/* SD3_WP */
-	MX53_PAD_EIM_DA12__GPIO3_12,
-	/* VGA */
-	MX53_PAD_EIM_OE__IPU_DI1_PIN7,
-	MX53_PAD_EIM_RW__IPU_DI1_PIN8,
-	/* DISPLB */
-	MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
-	MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
-	MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
-	MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
-	/* DISP0_POWER_EN */
-	MX53_PAD_EIM_D24__GPIO3_24,
-	/* DISP0 DET INT */
-	MX53_PAD_EIM_D31__GPIO3_31,
-	/* LVDS */
-	MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
-	MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
-	MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
-	MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
-	MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
-	MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
-	MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
-	MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
-	MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
-	MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	/* UART1 */
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-	/* CSI0 */
-	MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
-	MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
-	MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
-	MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
-	MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
-	MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
-	MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
-	MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
-	MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
-	MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
-	MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
-	/* DISPLAY */
-	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
-	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
-	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
-	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
-	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
-	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
-	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
-	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
-	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
-	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
-	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
-	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
-	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
-	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
-	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
-	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
-	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
-	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
-	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
-	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
-	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
-	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
-	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
-	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
-	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
-	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
-	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
-	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
-	/* Audio CLK*/
-	MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
-	/* PWM */
-	MX53_PAD_GPIO_1__PWM2_PWMO,
-	/* SPDIF */
-	MX53_PAD_GPIO_7__SPDIF_PLOCK,
-	MX53_PAD_GPIO_17__SPDIF_OUT1,
-	/* GPIO */
-	MX53_PAD_PATA_DA_1__GPIO7_7,		/* LED */
-	MX53_PAD_PATA_DA_2__GPIO7_8,
-	MX53_PAD_PATA_DATA5__GPIO2_5,
-	MX53_PAD_PATA_DATA6__GPIO2_6,
-	MX53_PAD_PATA_DATA14__GPIO2_14,
-	MX53_PAD_PATA_DATA15__GPIO2_15,
-	MX53_PAD_PATA_INTRQ__GPIO7_2,
-	MX53_PAD_EIM_WAIT__GPIO5_0,
-	MX53_PAD_NANDF_WP_B__GPIO6_9,
-	MX53_PAD_NANDF_RB0__GPIO6_10,
-	MX53_PAD_NANDF_CS1__GPIO6_14,
-	MX53_PAD_NANDF_CS2__GPIO6_15,
-	MX53_PAD_NANDF_CS3__GPIO6_16,
-	MX53_PAD_GPIO_5__GPIO1_5,
-	MX53_PAD_GPIO_16__GPIO7_11,
-	MX53_PAD_GPIO_8__GPIO1_8,
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
-{								\
-	.gpio		= gpio_num,				\
-	.type		= EV_KEY,				\
-	.code		= ev_code,				\
-	.active_low	= act_low,				\
-	.desc		= "btn " descr,				\
-	.wakeup		= wake,					\
-}
-
-static struct gpio_keys_button loco_buttons[] = {
-	GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
-	GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
-	GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data loco_button_data __initconst = {
-	.buttons        = loco_buttons,
-	.nbuttons       = ARRAY_SIZE(loco_buttons),
-};
-
-static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
-	.cd_gpio = LOCO_SD1_CD,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_NONE,
-};
-
-static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
-	.cd_gpio = LOCO_SD3_CD,
-	.wp_gpio = LOCO_SD3_WP,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_GPIO,
-};
-
-static inline void mx53_loco_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	gpio_direction_output(LOCO_FEC_PHY_RST, 0);
-	msleep(1);
-	gpio_set_value(LOCO_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_loco_fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static const struct gpio_led mx53loco_leds[] __initconst = {
-	{
-		.name			= "green",
-		.default_trigger	= "heartbeat",
-		.gpio			= LOCO_LED,
-	},
-};
-
-static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
-	.leds		= mx53loco_leds,
-	.num_leds	= ARRAY_SIZE(mx53loco_leds),
-};
-
-void __init imx53_qsb_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-					 ARRAY_SIZE(mx53_loco_pads));
-}
-
-static struct i2c_board_info mx53loco_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("mma8450", 0x1C),
-	},
-};
-
-static void __init mx53_loco_board_init(void)
-{
-	int ret;
-	imx53_soc_init();
-	imx53_qsb_common_init();
-
-	imx53_add_imx_uart(0, NULL);
-	mx53_loco_fec_reset();
-	imx53_add_fec(&mx53_loco_fec_data);
-	imx53_add_imx2_wdt(0, NULL);
-
-	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
-	if (ret)
-		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
-
-	i2c_register_board_info(0, mx53loco_i2c_devices,
-				ARRAY_SIZE(mx53loco_i2c_devices));
-	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
-	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
-	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
-	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
-	imx_add_gpio_keys(&loco_button_data);
-	gpio_led_register_device(-1, &mx53loco_leds_data);
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_loco_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 0, 0);
-}
-
-static struct sys_timer mx53_loco_timer = {
-	.init	= mx53_loco_timer_init,
-};
-
-MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_loco_timer,
-	.init_machine = mx53_loco_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
deleted file mode 100644
index 22c53c9..0000000
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "crm_regs.h"
-#include "devices-imx53.h"
-
-#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
-#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
-
-static iomux_v3_cfg_t mx53_smd_pads[] = {
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-
-	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-	MX53_PAD_PATA_DA_1__UART3_CTS,
-	MX53_PAD_PATA_DA_2__UART3_RTS,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	/* SD1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	/* SD2 */
-	MX53_PAD_SD2_CMD__ESDHC2_CMD,
-	MX53_PAD_SD2_CLK__ESDHC2_CLK,
-	MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
-	MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
-	MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
-	MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
-	/* SD3 */
-	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-};
-
-static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mx53_smd_init_uart(void)
-{
-	imx53_add_imx_uart(0, NULL);
-	imx53_add_imx_uart(1, NULL);
-	imx53_add_imx_uart(2, &mx53_smd_uart_data);
-}
-
-static inline void mx53_smd_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	gpio_direction_output(SMD_FEC_PHY_RST, 0);
-	msleep(1);
-	gpio_set_value(SMD_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_smd_fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static inline void mx53_smd_ahci_pwr_on(void)
-{
-	int ret;
-
-	/* Enable SATA PWR */
-	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
-			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
-	if (ret) {
-		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
-		return;
-	}
-}
-
-void __init imx53_smd_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-					 ARRAY_SIZE(mx53_smd_pads));
-}
-
-static void __init mx53_smd_board_init(void)
-{
-	imx53_soc_init();
-	imx53_smd_common_init();
-
-	mx53_smd_init_uart();
-	mx53_smd_fec_reset();
-	imx53_add_fec(&mx53_smd_fec_data);
-	imx53_add_imx2_wdt(0, NULL);
-	imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
-	imx53_add_sdhci_esdhc_imx(0, NULL);
-	imx53_add_sdhci_esdhc_imx(1, NULL);
-	imx53_add_sdhci_esdhc_imx(2, NULL);
-	mx53_smd_ahci_pwr_on();
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_smd_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_smd_timer = {
-	.init	= mx53_smd_timer_init,
-};
-
-MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_smd_timer,
-	.init_machine = mx53_smd_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
deleted file mode 100644
index 4cb2769..0000000
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ /dev/null
@@ -1,1675 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/of.h>
-
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk mx53_pll4_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-static struct clk emi_fast_clk;
-static struct clk ipu_clk;
-static struct clk mipi_hsc1_clk;
-static struct clk esdhc1_clk;
-static struct clk esdhc2_clk;
-static struct clk esdhc3_mx53_clk;
-
-#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
-
-/* calculate best pre and post dividers to get the required divider */
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
-	u32 max_pre, u32 max_post)
-{
-	if (div >= max_pre * max_post) {
-		*pre = max_pre;
-		*post = max_post;
-	} else if (div >= max_pre) {
-		u32 min_pre, temp_pre, old_err, err;
-		min_pre = DIV_ROUND_UP(div, max_post);
-		old_err = max_pre;
-		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
-			err = div % temp_pre;
-			if (err == 0) {
-				*pre = temp_pre;
-				break;
-			}
-			err = temp_pre - err;
-			if (err < old_err) {
-				old_err = err;
-				*pre = temp_pre;
-			}
-		}
-		*post = DIV_ROUND_UP(div, *pre);
-	} else {
-		*pre = div;
-		*post = 1;
-	}
-}
-
-static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
-{
-	u32 reg = __raw_readl(clk->enable_reg);
-
-	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-	reg |= mode << clk->enable_shift;
-
-	__raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
-	return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
-}
-
-static int _clk_ccgr_enable_inrun(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-	return 0;
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
-			   struct clk *m1, struct clk *m2, struct clk *m3)
-{
-	if (parent == m0)
-		return 0;
-	else if (parent == m1)
-		return 1;
-	else if (parent == m2)
-		return 2;
-	else if (parent == m3)
-		return 3;
-	else
-		BUG();
-
-	return -EINVAL;
-}
-
-static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
-{
-	if (pll == &pll1_main_clk)
-		return MX51_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
-		return MX51_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
-		return MX51_DPLL3_BASE;
-	else
-		BUG();
-
-	return NULL;
-}
-
-static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
-{
-	if (pll == &pll1_main_clk)
-		return MX53_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
-		return MX53_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
-		return MX53_DPLL3_BASE;
-	else if (pll == &mx53_pll4_sw_clk)
-		return MX53_DPLL4_BASE;
-	else
-		BUG();
-
-	return NULL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
-	if (cpu_is_mx51())
-		return _mx51_get_pll_base(pll);
-	else
-		return _mx53_get_pll_base(pll);
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
-	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
-	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
-	void __iomem *pllbase;
-	s64 temp;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
-	if (pll_hfsm == 0) {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
-	} else {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
-	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
-	mfi = (mfi <= 5) ? 5 : mfi;
-	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
-	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
-	/* Sign extend to 32-bits */
-	if (mfn >= 0x04000000) {
-		mfn |= 0xFC000000;
-		mfn_abs = -mfn;
-	}
-
-	ref_clk = 2 * parent_rate;
-	if (dbl != 0)
-		ref_clk *= 2;
-
-	ref_clk /= (pdf + 1);
-	temp = (u64) ref_clk * mfn_abs;
-	do_div(temp, mfd + 1);
-	if (mfn < 0)
-		temp = -temp;
-	temp = (ref_clk * mfi) + temp;
-
-	return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	long mfi, pdf, mfn, mfd = 999999;
-	s64 temp64;
-	unsigned long quad_parent_rate;
-	unsigned long pll_hfsm, dp_ctl;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	quad_parent_rate = 4 * parent_rate;
-	pdf = mfi = -1;
-	while (++pdf < 16 && mfi < 5)
-		mfi = rate * (pdf+1) / quad_parent_rate;
-	if (mfi > 15)
-		return -EINVAL;
-	pdf--;
-
-	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
-	do_div(temp64, quad_parent_rate/1000000);
-	mfn = (long)temp64;
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	/* use dpdck0_2 */
-	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	if (pll_hfsm == 0) {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
-	} else {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-
-	return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-	int i = 0;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	if (reg & MXC_PLL_DP_CTL_UPEN)
-		return 0;
-
-	reg |= MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-		if (reg & MXC_PLL_DP_CTL_LRF)
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: pll locking failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, step;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	/* When switching from pll_main_clk to a bypass clock, first select a
-	 * multiplexed clock in 'step_sel', then shift the glitchless mux
-	 * 'pll1_sw_clk_sel'.
-	 *
-	 * When switching back, do it in reverse order
-	 */
-	if (parent == &pll1_main_clk) {
-		/* Switch to pll1_main_clk */
-		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* step_clk mux switched to lp_apm, to save power. */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
-				MXC_CCM_CCSR_STEP_SEL_OFFSET);
-	} else {
-		if (parent == &lp_apm_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-		} else  if (parent == &pll2_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-		} else  if (parent == &pll3_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
-		} else
-			return -EINVAL;
-
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* Switch to step_clk */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-	}
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (clk->parent == &pll2_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-	} else if (clk->parent == &pll3_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
-	} else
-		div = 1;
-	return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-	else
-		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	if (parent == &osc_clk)
-		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-
-	return 0;
-}
-
-static unsigned long clk_cpu_get_rate(struct clk *clk)
-{
-	u32 cacrr, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cacrr = __raw_readl(MXC_CCM_CACRR);
-	div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
-	return parent_rate / div;
-}
-
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, cpu_podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cpu_podf = parent_rate / rate - 1;
-	/* use post divider to change freq */
-	reg = __raw_readl(MXC_CCM_CACRR);
-	reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
-	reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CACRR);
-
-	return 0;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-	int i = 0;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
-	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: Set parent for periph_apm clock failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else if (parent == &periph_apm_clk)
-		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	return 0;
-}
-
-static struct clk main_bus_clk = {
-	.parent = &pll2_sw_clk,
-	.set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
-	       MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
-	return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-	int i = 0;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: clk_ahb_set_rate failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8)
-		div = 8;
-	else if (div == 0)
-		div++;
-	return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-
-	/* Handshake with MAX when LPM is entered. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	if (cpu_is_mx51())
-		reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	else if (cpu_is_mx53())
-		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable_inwait(clk);
-
-	/* No Handshake with MAX when LPM is entered as its disabled. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	if (cpu_is_mx51())
-		reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	else if (cpu_is_mx53())
-		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
-	       MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
-	return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
-	u32 reg, prediv1, prediv2, podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
-		/* the main_bus_clk is the one before the DVFS engine */
-		reg = __raw_readl(MXC_CCM_CBCDR);
-		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
-		prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
-		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
-			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
-		return parent_rate / (prediv1 * prediv2 * podf);
-	} else if (clk->parent == &ipg_clk)
-		return parent_rate;
-	else
-		BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCMR);
-
-	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
-	if (parent == &ipg_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-	else if (parent == &lp_apm_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	else if (parent != &main_bus_clk)
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	return 0;
-}
-
-#define clk_nfc_set_parent	NULL
-
-static unsigned long clk_nfc_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
-	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
-	rate = clk_get_rate(clk->parent) / div;
-	WARN_ON(rate == 0);
-	return rate;
-}
-
-static unsigned long clk_nfc_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-
-	if (!rate)
-		return -EINVAL;
-
-	div = parent_rate / rate;
-
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 8)
-		return -EINVAL;
-
-	return parent_rate / div;
-
-}
-
-static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-
-	div = clk_get_rate(clk->parent) / rate;
-	if (div == 0)
-		div++;
-	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	while (__raw_readl(MXC_CCM_CDHIPR) &
-			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
-	}
-
-	return 0;
-}
-
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
-{
-	return external_high_reference;
-}
-
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
-	return external_low_reference;
-}
-
-static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
-	return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
-	return ckih2_reference;
-}
-
-static unsigned long clk_emi_slow_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
-	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
-		MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
-	rate = clk_get_rate(clk->parent) / div;
-
-	return rate;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
-	.get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
-	.get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
-	.get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
-	.get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- * 	CCM: Clock Controller Module
- *
- * PLL output -> |
- *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
-	.parent = &pll1_main_clk,
-	.set_parent = _clk_pll1_sw_set_parent,
-	.get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.set_rate = _clk_pll_set_rate,
-	.set_parent = _clk_pll2_sw_set_parent,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
-	.parent = &osc_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
-static struct clk mx53_pll4_sw_clk = {
-	.parent = &osc_clk,
-	.set_rate = _clk_pll_set_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
-	.parent = &osc_clk,
-	.set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
-	.parent = &pll1_sw_clk,
-	.set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
-	.parent = &pll1_sw_clk,
-	.get_rate = clk_cpu_get_rate,
-	.set_rate = clk_cpu_set_rate,
-};
-
-static struct clk ahb_clk = {
-	.parent = &main_bus_clk,
-	.get_rate = clk_ahb_get_rate,
-	.set_rate = _clk_ahb_set_rate,
-	.round_rate = _clk_ahb_round_rate,
-};
-
-static struct clk iim_clk = {
-	.parent = &ipg_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
-	.parent = &ahb_clk,
-	.get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
-	.parent = &lp_apm_clk,
-	.get_rate = clk_ipg_per_get_rate,
-	.set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk ahb_max_clk = {
-	.parent = &ahb_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-	.enable = _clk_max_enable,
-	.disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpc_dvfs_clk = {
-	.enable_reg = MXC_CCM_CCGR5,
-	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-};
-
-static struct clk gpt_32k_clk = {
-	.id = 0,
-	.parent = &ckil_clk,
-};
-
-static struct clk dummy_clk = {
-	.id = 0,
-};
-
-static struct clk emi_slow_clk = {
-	.parent = &pll2_sw_clk,
-	.enable_reg = MXC_CCM_CCGR5,
-	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-	.get_rate = clk_emi_slow_get_rate,
-};
-
-static int clk_ipu_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-
-	/* Enable handshake with IPU when certain clock rates are changed */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	/* Enable handshake with IPU when LPM is entered */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void clk_ipu_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable(clk);
-
-	/* Disable handshake with IPU whe dividers are changed */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg |= MXC_CCM_CCDR_IPU_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	/* Disable handshake with IPU when LPM is entered */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk ahbmux1_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk ipu_sec_clk = {
-	.parent = &emi_fast_clk,
-	.secondary = &ahbmux1_clk,
-};
-
-static struct clk ddr_hf_clk = {
-	.parent = &pll1_sw_clk,
-	.get_rate = _clk_ddr_hf_get_rate,
-};
-
-static struct clk ddr_clk = {
-	.parent = &ddr_hf_clk,
-};
-
-/* clock definitions for MIPI HSC unit which has been removed
- * from documentation, but not from hardware
- */
-static int _clk_hsc_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-	/* Handshake with IPU when certain clock rates are changed. */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void _clk_hsc_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable(clk);
-	/* No handshake with HSC as its not enabled. */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg |= MXC_CCM_CCDR_HSC_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk mipi_hsp_clk = {
-	.parent = &ipu_clk,
-	.enable_reg = MXC_CCM_CCGR4,
-	.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
-	.enable = _clk_hsc_enable,
-	.disable = _clk_hsc_disable,
-	.secondary = &mipi_hsc1_clk,
-};
-
-#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.round_rate	= pfx##_round_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_ccgr_enable,	\
-		.disable	= _clk_ccgr_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_max_enable,	\
-		.disable	= _clk_max_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define CLK_GET_RATE(name, nr, bitsname)				\
-static unsigned long clk_##name##_get_rate(struct clk *clk)		\
-{									\
-	u32 reg, pred, podf;						\
-									\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
-	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-									\
-	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
-			(pred + 1) * (podf + 1));			\
-}
-
-#define CLK_SET_PARENT(name, nr, bitsname)				\
-static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
-{									\
-	u32 reg, mux;							\
-									\
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
-			&pll3_sw_clk, &lp_apm_clk);			\
-	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
-		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
-	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
-									\
-	return 0;							\
-}
-
-#define CLK_SET_RATE(name, nr, bitsname)				\
-static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
-{									\
-	u32 reg, div, parent_rate;					\
-	u32 pre = 0, post = 0;						\
-									\
-	parent_rate = clk_get_rate(clk->parent);			\
-	div = parent_rate / rate;					\
-									\
-	if ((parent_rate / div) != rate)				\
-		return -EINVAL;						\
-									\
-	__calc_pre_post_dividers(div, &pre, &post,			\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
-									\
-	/* Set sdhc1 clock divider */					\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
-		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
-		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
-	reg |= (post - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-	reg |= (pre - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
-									\
-	return 0;							\
-}
-
-/* UART */
-CLK_GET_RATE(uart, 1, UART)
-CLK_SET_PARENT(uart, 1, UART)
-
-static struct clk uart_root_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_uart_get_rate,
-	.set_parent = clk_uart_set_parent,
-};
-
-/* USBOH3 */
-CLK_GET_RATE(usboh3, 1, USBOH3)
-CLK_SET_PARENT(usboh3, 1, USBOH3)
-
-static struct clk usboh3_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_usboh3_get_rate,
-	.set_parent = clk_usboh3_set_parent,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-};
-
-static struct clk usb_ahb_clk = {
-	.parent = &ipg_clk,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-};
-
-static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
-
-	if (parent == &pll3_sw_clk)
-		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
-
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-static struct clk usb_phy1_clk = {
-	.parent = &pll3_sw_clk,
-	.set_parent = clk_usb_phy1_set_parent,
-	.enable = _clk_ccgr_enable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
-	.disable = _clk_ccgr_disable,
-};
-
-/* eCSPI */
-CLK_GET_RATE(ecspi, 2, CSPI)
-CLK_SET_PARENT(ecspi, 1, CSPI)
-
-static struct clk ecspi_main_clk = {
-	.parent = &pll3_sw_clk,
-	.get_rate = clk_ecspi_get_rate,
-	.set_parent = clk_ecspi_set_parent,
-};
-
-/* eSDHC */
-CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-
-/* mx51 specific */
-CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-
-static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-	else if (parent == &esdhc2_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else if (parent == &esdhc2_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-/* mx53 specific */
-static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-	else if (parent == &esdhc3_mx53_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-
-static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else if (parent == &esdhc3_mx53_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
-	static struct clk name = {					\
-		.id		= i,					\
-		.enable_reg	= er,					\
-		.enable_shift	= es,					\
-		.get_rate	= gr,					\
-		.set_rate	= sr,					\
-		.enable		= e,					\
-		.disable	= d,					\
-		.parent		= p,					\
-		.secondary	= s,					\
-	}
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
-	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
-	NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart4_ipg_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart5_ipg_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
-DEFINE_CLOCK(uart4_clk, 3, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart4_ipg_clk);
-DEFINE_CLOCK(uart5_clk, 4, MXC_CCM_CCGR7, MXC_CCM_CCGRx_CG7_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart5_ipg_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
-
-DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_perclk, NULL);
-
-/* I2C */
-DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_perclk, NULL);
-DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(i2c3_mx53_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &ipg_perclk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* NFC */
-DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
-	clk_nfc, &emi_slow_clk, NULL);
-
-/* SSI */
-DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
-DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
-DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
-
-/* eCSPI */
-DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &spba_clk);
-DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
-DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
-
-/* CSPI */
-DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
-		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
-
-/* SDMA */
-DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
-		NULL, NULL, &ahb_clk, NULL);
-
-/* eSDHC */
-DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
-	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
-DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-
-/* mx51 specific */
-DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
-	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc3_clk = {
-	.id = 2,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc3_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc3_ipg_clk,
-};
-static struct clk esdhc4_clk = {
-	.id = 3,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc4_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc4_ipg_clk,
-};
-
-/* mx53 specific */
-static struct clk esdhc2_mx53_clk = {
-	.id = 2,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc2_mx53_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc3_ipg_clk,
-};
-
-DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
-	clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc4_mx53_clk = {
-	.id = 3,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc4_mx53_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc4_ipg_clk,
-};
-
-static struct clk sata_clk = {
-	.parent = &ipg_clk,
-	.enable = _clk_max_enable,
-	.enable_reg = MXC_CCM_CCGR4,
-	.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
-	.disable = _clk_max_disable,
-};
-
-static struct clk ahci_phy_clk = {
-	.parent = &usb_phy1_clk,
-};
-
-static struct clk ahci_dma_clk = {
-	.parent = &ahb_clk,
-};
-
-DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
-
-/* IPU */
-DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
-
-DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
-		NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
-		&ddr_clk, NULL);
-
-DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
-		NULL, NULL, &pll3_sw_clk, NULL);
-DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
-		NULL, NULL, &pll3_sw_clk, NULL);
-
-/* PATA */
-DEFINE_CLOCK(pata_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG0_OFFSET,
-		NULL, NULL, &ipg_clk, &spba_clk);
-
-#define _REGISTER_CLOCK(d, n, c) \
-       { \
-		.dev_id = d, \
-		.con_id = n, \
-		.clk = &c,   \
-       },
-
-static struct clk_lookup mx51_lookups[] = {
-	/* i.mx51 has the i.mx21 type uart */
-	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	/* i.mx51 has the i.mx27 type fec */
-	_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
-	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
-	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-	/* i.mx51 has the i.mx35 type sdma */
-	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
-	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
-	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
-	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
-	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-	/* i.mx51 has the i.mx35 type cspi */
-	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx51.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx51.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx51.2", NULL, esdhc3_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx51.3", NULL, esdhc4_clk)
-	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
-	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-	_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
-	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
-	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
-	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
-	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
-	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
-};
-
-static struct clk_lookup mx53_lookups[] = {
-	/* i.mx53 has the i.mx21 type uart */
-	_REGISTER_CLOCK("imx21-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx21-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx21-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK("imx21-uart.3", NULL, uart4_clk)
-	_REGISTER_CLOCK("imx21-uart.4", NULL, uart5_clk)
-	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	/* i.mx53 has the i.mx25 type fec */
-	_REGISTER_CLOCK("imx25-fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c3_mx53_clk)
-	/* i.mx53 has the i.mx51 type ecspi */
-	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-	/* i.mx53 has the i.mx25 type cspi */
-	_REGISTER_CLOCK("imx35-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx53.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx53.1", NULL, esdhc2_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx53.2", NULL, esdhc3_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx53.3", NULL, esdhc4_mx53_clk)
-	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-	/* i.mx53 has the i.mx35 type sdma */
-	_REGISTER_CLOCK("imx35-sdma", NULL, sdma_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
-	_REGISTER_CLOCK("pata_imx", NULL, pata_clk)
-	_REGISTER_CLOCK("imx53-ahci.0", "ahci", sata_clk)
-	_REGISTER_CLOCK("imx53-ahci.0", "ahci_phy", ahci_phy_clk)
-	_REGISTER_CLOCK("imx53-ahci.0", "ahci_dma", ahci_dma_clk)
-};
-
-static void clk_tree_init(void)
-{
-	u32 reg;
-
-	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
-	/*
-	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
-	 * 8MHz, its derived from lp_apm.
-	 *
-	 * FIXME: Verify if true for all boards
-	 */
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
-	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
-	__raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2)
-{
-	int i;
-
-	external_low_reference = ckil;
-	external_high_reference = ckih1;
-	ckih2_reference = ckih2;
-	oscillator_reference = osc;
-
-	for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
-		clkdev_add(&mx51_lookups[i]);
-
-	clk_tree_init();
-
-	clk_enable(&cpu_clk);
-	clk_enable(&main_bus_clk);
-
-	clk_enable(&iim_clk);
-	imx_print_silicon_rev("i.MX51", mx51_revision());
-	clk_disable(&iim_clk);
-
-	/* move usb_phy_clk to 24MHz */
-	clk_set_parent(&usb_phy1_clk, &osc_clk);
-
-	/* set the usboh3_clk parent to pll2_sw_clk */
-	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
-	/* Set SDHC parents to be PLL2 */
-	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
-
-	/* set SDHC root clock as 166.25MHZ*/
-	clk_set_rate(&esdhc1_clk, 166250000);
-	clk_set_rate(&esdhc2_clk, 166250000);
-
-	/* System timer */
-	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_INT_GPT);
-	return 0;
-}
-
-int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2)
-{
-	int i;
-
-	external_low_reference = ckil;
-	external_high_reference = ckih1;
-	ckih2_reference = ckih2;
-	oscillator_reference = osc;
-
-	for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
-		clkdev_add(&mx53_lookups[i]);
-
-	clk_tree_init();
-
-	clk_set_parent(&uart_root_clk, &pll3_sw_clk);
-	clk_enable(&cpu_clk);
-	clk_enable(&main_bus_clk);
-
-	clk_enable(&iim_clk);
-	imx_print_silicon_rev("i.MX53", mx53_revision());
-	clk_disable(&iim_clk);
-
-	/* Set SDHC parents to be PLL2 */
-	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-	clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
-
-	/* set SDHC root clock as 200MHZ*/
-	clk_set_rate(&esdhc1_clk, 200000000);
-	clk_set_rate(&esdhc3_mx53_clk, 200000000);
-
-	/* System timer */
-	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
-		MX53_INT_GPT);
-	return 0;
-}
-
-#ifdef CONFIG_OF
-static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
-				   unsigned long *ckih1, unsigned long *ckih2)
-{
-	struct device_node *np;
-
-	/* retrieve the freqency of fixed clocks from device tree */
-	for_each_compatible_node(np, NULL, "fixed-clock") {
-		u32 rate;
-		if (of_property_read_u32(np, "clock-frequency", &rate))
-			continue;
-
-		if (of_device_is_compatible(np, "fsl,imx-ckil"))
-			*ckil = rate;
-		else if (of_device_is_compatible(np, "fsl,imx-osc"))
-			*osc = rate;
-		else if (of_device_is_compatible(np, "fsl,imx-ckih1"))
-			*ckih1 = rate;
-		else if (of_device_is_compatible(np, "fsl,imx-ckih2"))
-			*ckih2 = rate;
-	}
-}
-
-int __init mx51_clocks_init_dt(void)
-{
-	unsigned long ckil, osc, ckih1, ckih2;
-
-	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
-	return mx51_clocks_init(ckil, osc, ckih1, ckih2);
-}
-
-int __init mx53_clocks_init_dt(void)
-{
-	unsigned long ckil, osc, ckih1, ckih2;
-
-	clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
-	return mx53_clocks_init(ckil, osc, ckih1, ckih2);
-}
-#endif
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
deleted file mode 100644
index 5e2e7a8..0000000
--- a/arch/arm/mach-mx5/cpu.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * This file contains the CPU initialization code.
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-
-static int mx5_cpu_rev = -1;
-
-#define IIM_SREV 0x24
-#define MX50_HW_ADADIG_DIGPROG	0xB0
-
-static int get_mx51_srev(void)
-{
-	void __iomem *iim_base = MX51_IO_ADDRESS(MX51_IIM_BASE_ADDR);
-	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
-	switch (rev) {
-	case 0x0:
-		return IMX_CHIP_REVISION_2_0;
-	case 0x10:
-		return IMX_CHIP_REVISION_3_0;
-	default:
-		return IMX_CHIP_REVISION_UNKNOWN;
-	}
-}
-
-/*
- * Returns:
- *	the silicon revision of the cpu
- *	-EINVAL - not a mx51
- */
-int mx51_revision(void)
-{
-	if (!cpu_is_mx51())
-		return -EINVAL;
-
-	if (mx5_cpu_rev == -1)
-		mx5_cpu_rev = get_mx51_srev();
-
-	return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx51_revision);
-
-#ifdef CONFIG_NEON
-
-/*
- * All versions of the silicon before Rev. 3 have broken NEON implementations.
- * Dependent on link order - so the assumption is that vfp_init is called
- * before us.
- */
-static int __init mx51_neon_fixup(void)
-{
-	if (!cpu_is_mx51())
-		return 0;
-
-	if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
-			(elf_hwcap & HWCAP_NEON)) {
-		elf_hwcap &= ~HWCAP_NEON;
-		pr_info("Turning off NEON support, detected broken NEON implementation\n");
-	}
-	return 0;
-}
-
-late_initcall(mx51_neon_fixup);
-#endif
-
-static int get_mx53_srev(void)
-{
-	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
-	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
-
-	switch (rev) {
-	case 0x0:
-		return IMX_CHIP_REVISION_1_0;
-	case 0x2:
-		return IMX_CHIP_REVISION_2_0;
-	case 0x3:
-		return IMX_CHIP_REVISION_2_1;
-	default:
-		return IMX_CHIP_REVISION_UNKNOWN;
-	}
-}
-
-/*
- * Returns:
- *	the silicon revision of the cpu
- *	-EINVAL - not a mx53
- */
-int mx53_revision(void)
-{
-	if (!cpu_is_mx53())
-		return -EINVAL;
-
-	if (mx5_cpu_rev == -1)
-		mx5_cpu_rev = get_mx53_srev();
-
-	return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx53_revision);
-
-static int get_mx50_srev(void)
-{
-	void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
-	u32 rev;
-
-	if (!anatop) {
-		mx5_cpu_rev = -EINVAL;
-		return 0;
-	}
-
-	rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
-	rev &= 0xff;
-
-	iounmap(anatop);
-	if (rev == 0x0)
-		return IMX_CHIP_REVISION_1_0;
-	else if (rev == 0x1)
-		return IMX_CHIP_REVISION_1_1;
-	return 0;
-}
-
-/*
- * Returns:
- *	the silicon revision of the cpu
- *	-EINVAL - not a mx50
- */
-int mx50_revision(void)
-{
-	if (!cpu_is_mx50())
-		return -EINVAL;
-
-	if (mx5_cpu_rev == -1)
-		mx5_cpu_rev = get_mx50_srev();
-
-	return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx50_revision);
-
-static int __init post_cpu_init(void)
-{
-	unsigned int reg;
-	void __iomem *base;
-
-	if (cpu_is_mx51() || cpu_is_mx53()) {
-		if (cpu_is_mx51())
-			base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
-		else
-			base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);
-
-		__raw_writel(0x0, base + 0x40);
-		__raw_writel(0x0, base + 0x44);
-		__raw_writel(0x0, base + 0x48);
-		__raw_writel(0x0, base + 0x4C);
-		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-		__raw_writel(reg, base + 0x50);
-
-		if (cpu_is_mx51())
-			base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
-		else
-			base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);
-
-		__raw_writel(0x0, base + 0x40);
-		__raw_writel(0x0, base + 0x44);
-		__raw_writel(0x0, base + 0x48);
-		__raw_writel(0x0, base + 0x4C);
-		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
-		__raw_writel(reg, base + 0x50);
-	}
-
-	return 0;
-}
-
-postcore_initcall(post_cpu_init);
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.c b/arch/arm/mach-mx5/cpu_op-mx51.c
deleted file mode 100644
index 9d34c3d..0000000
--- a/arch/arm/mach-mx5/cpu_op-mx51.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/types.h>
-#include <mach/hardware.h>
-#include <linux/kernel.h>
-
-static struct cpu_op mx51_cpu_op[] = {
-	{
-	.cpu_rate = 160000000,},
-	{
-	.cpu_rate = 800000000,},
-};
-
-struct cpu_op *mx51_get_cpu_op(int *op)
-{
-	*op = ARRAY_SIZE(mx51_cpu_op);
-	return mx51_cpu_op;
-}
diff --git a/arch/arm/mach-mx5/cpu_op-mx51.h b/arch/arm/mach-mx5/cpu_op-mx51.h
deleted file mode 100644
index 97477fe..0000000
--- a/arch/arm/mach-mx5/cpu_op-mx51.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-extern struct cpu_op *mx51_get_cpu_op(int *op);
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
deleted file mode 100644
index 5e11ba7..0000000
--- a/arch/arm/mach-mx5/crm_regs.h
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
-
-#define MX51_CCM_BASE		MX51_IO_ADDRESS(MX51_CCM_BASE_ADDR)
-#define MX51_DPLL1_BASE		MX51_IO_ADDRESS(MX51_PLL1_BASE_ADDR)
-#define MX51_DPLL2_BASE		MX51_IO_ADDRESS(MX51_PLL2_BASE_ADDR)
-#define MX51_DPLL3_BASE		MX51_IO_ADDRESS(MX51_PLL3_BASE_ADDR)
-#define MX51_CORTEXA8_BASE	MX51_IO_ADDRESS(MX51_ARM_BASE_ADDR)
-#define MX51_GPC_BASE		MX51_IO_ADDRESS(MX51_GPC_BASE_ADDR)
-
-/*MX53*/
-#define MX53_CCM_BASE		MX53_IO_ADDRESS(MX53_CCM_BASE_ADDR)
-#define MX53_DPLL1_BASE		MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
-#define MX53_DPLL2_BASE		MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
-#define MX53_DPLL3_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-
-/* PLL Register Offsets */
-#define MXC_PLL_DP_CTL			0x00
-#define MXC_PLL_DP_CONFIG		0x04
-#define MXC_PLL_DP_OP			0x08
-#define MXC_PLL_DP_MFD			0x0C
-#define MXC_PLL_DP_MFN			0x10
-#define MXC_PLL_DP_MFNMINUS		0x14
-#define MXC_PLL_DP_MFNPLUS		0x18
-#define MXC_PLL_DP_HFS_OP		0x1C
-#define MXC_PLL_DP_HFS_MFD		0x20
-#define MXC_PLL_DP_HFS_MFN		0x24
-#define MXC_PLL_DP_MFN_TOGC		0x28
-#define MXC_PLL_DP_DESTAT		0x2c
-
-/* PLL Register Bit definitions */
-#define MXC_PLL_DP_CTL_MUL_CTRL		0x2000
-#define MXC_PLL_DP_CTL_DPDCK0_2_EN	0x1000
-#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET	12
-#define MXC_PLL_DP_CTL_ADE		0x800
-#define MXC_PLL_DP_CTL_REF_CLK_DIV	0x400
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK	(3 << 8)
-#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET	8
-#define MXC_PLL_DP_CTL_HFSM		0x80
-#define MXC_PLL_DP_CTL_PRE		0x40
-#define MXC_PLL_DP_CTL_UPEN		0x20
-#define MXC_PLL_DP_CTL_RST		0x10
-#define MXC_PLL_DP_CTL_RCP		0x8
-#define MXC_PLL_DP_CTL_PLM		0x4
-#define MXC_PLL_DP_CTL_BRM0		0x2
-#define MXC_PLL_DP_CTL_LRF		0x1
-
-#define MXC_PLL_DP_CONFIG_BIST		0x8
-#define MXC_PLL_DP_CONFIG_SJC_CE	0x4
-#define MXC_PLL_DP_CONFIG_AREN		0x2
-#define MXC_PLL_DP_CONFIG_LDREQ		0x1
-
-#define MXC_PLL_DP_OP_MFI_OFFSET	4
-#define MXC_PLL_DP_OP_MFI_MASK		(0xF << 4)
-#define MXC_PLL_DP_OP_PDF_OFFSET	0
-#define MXC_PLL_DP_OP_PDF_MASK		0xF
-
-#define MXC_PLL_DP_MFD_OFFSET		0
-#define MXC_PLL_DP_MFD_MASK		0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_OFFSET		0x0
-#define MXC_PLL_DP_MFN_MASK		0x07FFFFFF
-
-#define MXC_PLL_DP_MFN_TOGC_TOG_DIS	(1 << 17)
-#define MXC_PLL_DP_MFN_TOGC_TOG_EN	(1 << 16)
-#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET	0x0
-#define MXC_PLL_DP_MFN_TOGC_CNT_MASK	0xFFFF
-
-#define MXC_PLL_DP_DESTAT_TOG_SEL	(1 << 31)
-#define MXC_PLL_DP_DESTAT_MFN		0x07FFFFFF
-
-/* Register addresses of CCM*/
-#define MXC_CCM_CCR		(MX51_CCM_BASE + 0x00)
-#define MXC_CCM_CCDR		(MX51_CCM_BASE + 0x04)
-#define MXC_CCM_CSR		(MX51_CCM_BASE + 0x08)
-#define MXC_CCM_CCSR		(MX51_CCM_BASE + 0x0C)
-#define MXC_CCM_CACRR		(MX51_CCM_BASE + 0x10)
-#define MXC_CCM_CBCDR		(MX51_CCM_BASE + 0x14)
-#define MXC_CCM_CBCMR		(MX51_CCM_BASE + 0x18)
-#define MXC_CCM_CSCMR1		(MX51_CCM_BASE + 0x1C)
-#define MXC_CCM_CSCMR2		(MX51_CCM_BASE + 0x20)
-#define MXC_CCM_CSCDR1		(MX51_CCM_BASE + 0x24)
-#define MXC_CCM_CS1CDR		(MX51_CCM_BASE + 0x28)
-#define MXC_CCM_CS2CDR		(MX51_CCM_BASE + 0x2C)
-#define MXC_CCM_CDCDR		(MX51_CCM_BASE + 0x30)
-#define MXC_CCM_CHSCDR		(MX51_CCM_BASE + 0x34)
-#define MXC_CCM_CSCDR2		(MX51_CCM_BASE + 0x38)
-#define MXC_CCM_CSCDR3		(MX51_CCM_BASE + 0x3C)
-#define MXC_CCM_CSCDR4		(MX51_CCM_BASE + 0x40)
-#define MXC_CCM_CWDR		(MX51_CCM_BASE + 0x44)
-#define MXC_CCM_CDHIPR		(MX51_CCM_BASE + 0x48)
-#define MXC_CCM_CDCR		(MX51_CCM_BASE + 0x4C)
-#define MXC_CCM_CTOR		(MX51_CCM_BASE + 0x50)
-#define MXC_CCM_CLPCR		(MX51_CCM_BASE + 0x54)
-#define MXC_CCM_CISR		(MX51_CCM_BASE + 0x58)
-#define MXC_CCM_CIMR		(MX51_CCM_BASE + 0x5C)
-#define MXC_CCM_CCOSR		(MX51_CCM_BASE + 0x60)
-#define MXC_CCM_CGPR		(MX51_CCM_BASE + 0x64)
-#define MXC_CCM_CCGR0		(MX51_CCM_BASE + 0x68)
-#define MXC_CCM_CCGR1		(MX51_CCM_BASE + 0x6C)
-#define MXC_CCM_CCGR2		(MX51_CCM_BASE + 0x70)
-#define MXC_CCM_CCGR3		(MX51_CCM_BASE + 0x74)
-#define MXC_CCM_CCGR4		(MX51_CCM_BASE + 0x78)
-#define MXC_CCM_CCGR5		(MX51_CCM_BASE + 0x7C)
-#define MXC_CCM_CCGR6		(MX51_CCM_BASE + 0x80)
-#define MXC_CCM_CCGR7		(MX51_CCM_BASE + 0x84)
-
-#define MXC_CCM_CMEOR		(MX51_CCM_BASE + 0x84)
-
-/* Define the bits in register CCR */
-#define MXC_CCM_CCR_COSC_EN		(1 << 12)
-#define MXC_CCM_CCR_FPM_MULT_MASK	(1 << 11)
-#define MXC_CCM_CCR_CAMP2_EN		(1 << 10)
-#define MXC_CCM_CCR_CAMP1_EN		(1 << 9)
-#define MXC_CCM_CCR_FPM_EN		(1 << 8)
-#define MXC_CCM_CCR_OSCNT_OFFSET	(0)
-#define MXC_CCM_CCR_OSCNT_MASK	(0xFF)
-
-/* Define the bits in register CCDR */
-#define MXC_CCM_CCDR_HSC_HS_MASK	(0x1 << 18)
-#define MXC_CCM_CCDR_IPU_HS_MASK	(0x1 << 17)
-#define MXC_CCM_CCDR_EMI_HS_MASK	(0x1 << 16)
-
-/* Define the bits in register CSR */
-#define MXC_CCM_CSR_COSR_READY	(1 << 5)
-#define MXC_CCM_CSR_LVS_VALUE	(1 << 4)
-#define MXC_CCM_CSR_CAMP2_READY	(1 << 3)
-#define MXC_CCM_CSR_CAMP1_READY	(1 << 2)
-#define MXC_CCM_CSR_FPM_READY	(1 << 1)
-#define MXC_CCM_CSR_REF_EN_B	(1 << 0)
-
-/* Define the bits in register CCSR */
-#define MXC_CCM_CCSR_LP_APM_SEL		(0x1 << 9)
-#define MXC_CCM_CCSR_STEP_SEL_OFFSET	(7)
-#define MXC_CCM_CCSR_STEP_SEL_MASK	(0x3 << 7)
-#define MXC_CCM_CCSR_STEP_SEL_LP_APM	   0
-#define MXC_CCM_CCSR_STEP_SEL_PLL1_BYPASS  1 /* Only when JTAG connected? */
-#define MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED 2
-#define MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED 3
-#define MXC_CCM_CCSR_PLL2_PODF_OFFSET	(5)
-#define MXC_CCM_CCSR_PLL2_PODF_MASK	(0x3 << 5)
-#define MXC_CCM_CCSR_PLL3_PODF_OFFSET	(3)
-#define MXC_CCM_CCSR_PLL3_PODF_MASK	(0x3 << 3)
-#define MXC_CCM_CCSR_PLL1_SW_CLK_SEL	(1 << 2) /* 0: pll1_main_clk,
-						    1: step_clk */
-#define MXC_CCM_CCSR_PLL2_SW_CLK_SEL	(1 << 1)
-#define MXC_CCM_CCSR_PLL3_SW_CLK_SEL	(1 << 0)
-
-/* Define the bits in register CACRR */
-#define MXC_CCM_CACRR_ARM_PODF_OFFSET	(0)
-#define MXC_CCM_CACRR_ARM_PODF_MASK	(0x7)
-
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL		(0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET		(30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL		(0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET		(27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK		(0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET		(22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK		(0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET		(19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK		(0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET		(16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK		(0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET		(13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK		(0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET		(10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK		(0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET		(8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK		(0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET	(6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK		(0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET	(3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK		(0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET	(0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET	(12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK	(0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET	(10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK		(0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET	(8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK	(0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET	(6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK	(0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET	(4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL	(0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL	(0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET		(30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK		(0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET		(28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK		(0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET		(26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL			(0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL			(0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL			(0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET		(8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK		(0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL			(0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL			(0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET		(4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL		(0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL		(0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)		(26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)		(0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET		(20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK			(0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET		(18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK		(0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET		(16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET		(10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK			(0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM			(0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET		(6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK		(0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM			(1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM			(1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET		(0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK		(0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK		(0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET	(11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK	(0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET		(8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK		(0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK		(0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET		(3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK		(0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK		(0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET		(28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK			(0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK			(0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET		(3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK			(0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET		(0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK			(0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET		(12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK		(0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK		(0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET		(3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK		(0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET	(9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET	(6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET	(0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CDHIPR */
-#define MXC_CCM_CDHIPR_ARM_PODF_BUSY			(1 << 16)
-#define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY		(1 << 8)
-#define MXC_CCM_CDHIPR_DDR_PODF_BUSY			(1 << 7)
-#define MXC_CCM_CDHIPR_EMI_CLK_SEL_BUSY			(1 << 6)
-#define MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY		(1 << 5)
-#define MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY	(1 << 4)
-#define MXC_CCM_CDHIPR_AHB_PODF_BUSY			(1 << 3)
-#define MXC_CCM_CDHIPR_EMI_PODF_BUSY			(1 << 2)
-#define MXC_CCM_CDHIPR_AXI_B_PODF_BUSY			(1 << 1)
-#define MXC_CCM_CDHIPR_AXI_A_PODF_BUSY			(1 << 0)
-
-/* Define the bits in register CDCR */
-#define MXC_CCM_CDCR_ARM_FREQ_SHIFT_DIVIDER		(0x1 << 2)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_OFFSET	(0)
-#define MXC_CCM_CDCR_PERIPH_CLK_DVFS_PODF_MASK		(0x3)
-
-/* Define the bits in register CLPCR */
-#define MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS		(0x1 << 23)
-#define MXC_CCM_CLPCR_BYPASS_SCC_LPM_HS		(0x1 << 22)
-#define MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 21)
-#define MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS		(0x1 << 25)
-#define MXC_CCM_CLPCR_BYPASS_SDMA_LPM_HS	(0x1 << 20)
-#define MXC_CCM_CLPCR_BYPASS_EMI_LPM_HS		(0x1 << 19)
-#define MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS		(0x1 << 18)
-#define MXC_CCM_CLPCR_BYPASS_RTIC_LPM_HS	(0x1 << 17)
-#define MXC_CCM_CLPCR_BYPASS_RNGC_LPM_HS	(0x1 << 16)
-#define MXC_CCM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
-#define MXC_CCM_CLPCR_STBY_COUNT_OFFSET		(9)
-#define MXC_CCM_CLPCR_STBY_COUNT_MASK		(0x3 << 9)
-#define MXC_CCM_CLPCR_VSTBY			(0x1 << 8)
-#define MXC_CCM_CLPCR_DIS_REF_OSC		(0x1 << 7)
-#define MXC_CCM_CLPCR_SBYOS			(0x1 << 6)
-#define MXC_CCM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_OFFSET	(3)
-#define MXC_CCM_CLPCR_LPSR_CLK_SEL_MASK		(0x3 << 3)
-#define MXC_CCM_CLPCR_LPM_OFFSET		(0)
-#define MXC_CCM_CLPCR_LPM_MASK			(0x3)
-
-/* Define the bits in register CISR */
-#define MXC_CCM_CISR_ARM_PODF_LOADED			(0x1 << 25)
-#define MXC_CCM_CISR_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
-#define MXC_CCM_CISR_AHB_PODF_LOADED			(0x1 << 20)
-#define MXC_CCM_CISR_EMI_PODF_LOADED			(0x1 << 19)
-#define MXC_CCM_CISR_AXI_B_PODF_LOADED			(0x1 << 18)
-#define MXC_CCM_CISR_AXI_A_PODF_LOADED			(0x1 << 17)
-#define MXC_CCM_CISR_DIVIDER_LOADED			(0x1 << 16)
-#define MXC_CCM_CISR_COSC_READY				(0x1 << 6)
-#define MXC_CCM_CISR_CKIH2_READY			(0x1 << 5)
-#define MXC_CCM_CISR_CKIH_READY				(0x1 << 4)
-#define MXC_CCM_CISR_FPM_READY				(0x1 << 3)
-#define MXC_CCM_CISR_LRF_PLL3				(0x1 << 2)
-#define MXC_CCM_CISR_LRF_PLL2				(0x1 << 1)
-#define MXC_CCM_CISR_LRF_PLL1				(0x1)
-
-/* Define the bits in register CIMR */
-#define MXC_CCM_CIMR_MASK_ARM_PODF_LOADED		(0x1 << 25)
-#define MXC_CCM_CIMR_MASK_NFC_IPG_INT_MEM_PODF_LOADED	(0x1 << 21)
-#define MXC_CCM_CIMR_MASK_EMI_PODF_LOADED		(0x1 << 20)
-#define MXC_CCM_CIMR_MASK_AXI_C_PODF_LOADED		(0x1 << 19)
-#define MXC_CCM_CIMR_MASK_AXI_B_PODF_LOADED		(0x1 << 18)
-#define MXC_CCM_CIMR_MASK_AXI_A_PODF_LOADED		(0x1 << 17)
-#define MXC_CCM_CIMR_MASK_DIVIDER_LOADED		(0x1 << 16)
-#define MXC_CCM_CIMR_MASK_COSC_READY			(0x1 << 5)
-#define MXC_CCM_CIMR_MASK_CKIH_READY			(0x1 << 4)
-#define MXC_CCM_CIMR_MASK_FPM_READY			(0x1 << 3)
-#define MXC_CCM_CIMR_MASK_LRF_PLL3			(0x1 << 2)
-#define MXC_CCM_CIMR_MASK_LRF_PLL2			(0x1 << 1)
-#define MXC_CCM_CIMR_MASK_LRF_PLL1			(0x1)
-
-/* Define the bits in register CCOSR */
-#define MXC_CCM_CCOSR_CKO2_EN_OFFSET			(0x1 << 24)
-#define MXC_CCM_CCOSR_CKO2_DIV_OFFSET			(21)
-#define MXC_CCM_CCOSR_CKO2_DIV_MASK			(0x7 << 21)
-#define MXC_CCM_CCOSR_CKO2_SEL_OFFSET			(16)
-#define MXC_CCM_CCOSR_CKO2_SEL_MASK			(0x1F << 16)
-#define MXC_CCM_CCOSR_CKOL_EN				(0x1 << 7)
-#define MXC_CCM_CCOSR_CKOL_DIV_OFFSET			(4)
-#define MXC_CCM_CCOSR_CKOL_DIV_MASK			(0x7 << 4)
-#define MXC_CCM_CCOSR_CKOL_SEL_OFFSET			(0)
-#define MXC_CCM_CCOSR_CKOL_SEL_MASK			(0xF)
-
-/* Define the bits in registers CGPR */
-#define MXC_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE		(0x1 << 4)
-#define MXC_CCM_CGPR_FPM_SEL				(0x1 << 3)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_OFFSET		(0)
-#define MXC_CCM_CGPR_VL_L2BIST_CLKDIV_MASK		(0x7)
-
-/* Define the bits in registers CCGRx */
-#define MXC_CCM_CCGRx_CG_MASK				0x3
-#define MXC_CCM_CCGRx_MOD_OFF				0x0
-#define MXC_CCM_CCGRx_MOD_ON				0x3
-#define MXC_CCM_CCGRx_MOD_IDLE				0x1
-
-#define MXC_CCM_CCGRx_CG15_MASK				(0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK				(0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK				(0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK				(0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK				(0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK				(0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK				(0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK				(0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK				(0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK				(0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK				(0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK				(0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK				(0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK				(0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET			30
-#define MXC_CCM_CCGRx_CG14_OFFSET			28
-#define MXC_CCM_CCGRx_CG13_OFFSET			26
-#define MXC_CCM_CCGRx_CG12_OFFSET			24
-#define MXC_CCM_CCGRx_CG11_OFFSET			22
-#define MXC_CCM_CCGRx_CG10_OFFSET			20
-#define MXC_CCM_CCGRx_CG9_OFFSET			18
-#define MXC_CCM_CCGRx_CG8_OFFSET			16
-#define MXC_CCM_CCGRx_CG7_OFFSET			14
-#define MXC_CCM_CCGRx_CG6_OFFSET			12
-#define MXC_CCM_CCGRx_CG5_OFFSET			10
-#define MXC_CCM_CCGRx_CG4_OFFSET			8
-#define MXC_CCM_CCGRx_CG3_OFFSET			6
-#define MXC_CCM_CCGRx_CG2_OFFSET			4
-#define MXC_CCM_CCGRx_CG1_OFFSET			2
-#define MXC_CCM_CCGRx_CG0_OFFSET			0
-
-#define MXC_DPTC_LP_BASE	(MX51_GPC_BASE + 0x80)
-#define MXC_DPTC_GP_BASE	(MX51_GPC_BASE + 0x100)
-#define MXC_DVFS_CORE_BASE	(MX51_GPC_BASE + 0x180)
-#define MXC_DPTC_PER_BASE	(MX51_GPC_BASE + 0x1C0)
-#define MXC_PGC_IPU_BASE	(MX51_GPC_BASE + 0x220)
-#define MXC_PGC_VPU_BASE	(MX51_GPC_BASE + 0x240)
-#define MXC_PGC_GPU_BASE	(MX51_GPC_BASE + 0x260)
-#define MXC_SRPG_NEON_BASE	(MX51_GPC_BASE + 0x280)
-#define MXC_SRPG_ARM_BASE	(MX51_GPC_BASE + 0x2A0)
-#define MXC_SRPG_EMPGC0_BASE	(MX51_GPC_BASE + 0x2C0)
-#define MXC_SRPG_EMPGC1_BASE	(MX51_GPC_BASE + 0x2D0)
-#define MXC_SRPG_MEGAMIX_BASE	(MX51_GPC_BASE + 0x2E0)
-#define MXC_SRPG_EMI_BASE	(MX51_GPC_BASE + 0x300)
-
-/* CORTEXA8 platform */
-#define MXC_CORTEXA8_PLAT_PVID		(MX51_CORTEXA8_BASE + 0x0)
-#define MXC_CORTEXA8_PLAT_GPC		(MX51_CORTEXA8_BASE + 0x4)
-#define MXC_CORTEXA8_PLAT_PIC		(MX51_CORTEXA8_BASE + 0x8)
-#define MXC_CORTEXA8_PLAT_LPC		(MX51_CORTEXA8_BASE + 0xC)
-#define MXC_CORTEXA8_PLAT_NEON_LPC	(MX51_CORTEXA8_BASE + 0x10)
-#define MXC_CORTEXA8_PLAT_ICGC		(MX51_CORTEXA8_BASE + 0x14)
-#define MXC_CORTEXA8_PLAT_AMC		(MX51_CORTEXA8_BASE + 0x18)
-#define MXC_CORTEXA8_PLAT_NMC		(MX51_CORTEXA8_BASE + 0x20)
-#define MXC_CORTEXA8_PLAT_NMS		(MX51_CORTEXA8_BASE + 0x24)
-
-/* DVFS CORE */
-#define MXC_DVFSTHRS		(MXC_DVFS_CORE_BASE + 0x00)
-#define MXC_DVFSCOUN		(MXC_DVFS_CORE_BASE + 0x04)
-#define MXC_DVFSSIG1		(MXC_DVFS_CORE_BASE + 0x08)
-#define MXC_DVFSSIG0		(MXC_DVFS_CORE_BASE + 0x0C)
-#define MXC_DVFSGPC0		(MXC_DVFS_CORE_BASE + 0x10)
-#define MXC_DVFSGPC1		(MXC_DVFS_CORE_BASE + 0x14)
-#define MXC_DVFSGPBT		(MXC_DVFS_CORE_BASE + 0x18)
-#define MXC_DVFSEMAC		(MXC_DVFS_CORE_BASE + 0x1C)
-#define MXC_DVFSCNTR		(MXC_DVFS_CORE_BASE + 0x20)
-#define MXC_DVFSLTR0_0		(MXC_DVFS_CORE_BASE + 0x24)
-#define MXC_DVFSLTR0_1		(MXC_DVFS_CORE_BASE + 0x28)
-#define MXC_DVFSLTR1_0		(MXC_DVFS_CORE_BASE + 0x2C)
-#define MXC_DVFSLTR1_1		(MXC_DVFS_CORE_BASE + 0x30)
-#define MXC_DVFSPT0 		(MXC_DVFS_CORE_BASE + 0x34)
-#define MXC_DVFSPT1 		(MXC_DVFS_CORE_BASE + 0x38)
-#define MXC_DVFSPT2 		(MXC_DVFS_CORE_BASE + 0x3C)
-#define MXC_DVFSPT3 		(MXC_DVFS_CORE_BASE + 0x40)
-
-/* GPC */
-#define MXC_GPC_CNTR		(MX51_GPC_BASE + 0x0)
-#define MXC_GPC_PGR		(MX51_GPC_BASE + 0x4)
-#define MXC_GPC_VCR		(MX51_GPC_BASE + 0x8)
-#define MXC_GPC_ALL_PU		(MX51_GPC_BASE + 0xC)
-#define MXC_GPC_NEON		(MX51_GPC_BASE + 0x10)
-#define MXC_GPC_PGR_ARMPG_OFFSET	8
-#define MXC_GPC_PGR_ARMPG_MASK		(3 << 8)
-
-/* PGC */
-#define MXC_PGC_IPU_PGCR	(MXC_PGC_IPU_BASE + 0x0)
-#define MXC_PGC_IPU_PGSR	(MXC_PGC_IPU_BASE + 0xC)
-#define MXC_PGC_VPU_PGCR	(MXC_PGC_VPU_BASE + 0x0)
-#define MXC_PGC_VPU_PGSR	(MXC_PGC_VPU_BASE + 0xC)
-#define MXC_PGC_GPU_PGCR	(MXC_PGC_GPU_BASE + 0x0)
-#define MXC_PGC_GPU_PGSR	(MXC_PGC_GPU_BASE + 0xC)
-
-#define MXC_PGCR_PCR		1
-#define MXC_SRPGCR_PCR		1
-#define MXC_EMPGCR_PCR		1
-#define MXC_PGSR_PSR		1
-
-
-#define MXC_CORTEXA8_PLAT_LPC_DSM	(1 << 0)
-#define MXC_CORTEXA8_PLAT_LPC_DBG_DSM	(1 << 1)
-
-/* SRPG */
-#define MXC_SRPG_NEON_SRPGCR	(MXC_SRPG_NEON_BASE + 0x0)
-#define MXC_SRPG_NEON_PUPSCR	(MXC_SRPG_NEON_BASE + 0x4)
-#define MXC_SRPG_NEON_PDNSCR	(MXC_SRPG_NEON_BASE + 0x8)
-
-#define MXC_SRPG_ARM_SRPGCR	(MXC_SRPG_ARM_BASE + 0x0)
-#define MXC_SRPG_ARM_PUPSCR	(MXC_SRPG_ARM_BASE + 0x4)
-#define MXC_SRPG_ARM_PDNSCR	(MXC_SRPG_ARM_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC0_SRPGCR	(MXC_SRPG_EMPGC0_BASE + 0x0)
-#define MXC_SRPG_EMPGC0_PUPSCR	(MXC_SRPG_EMPGC0_BASE + 0x4)
-#define MXC_SRPG_EMPGC0_PDNSCR	(MXC_SRPG_EMPGC0_BASE + 0x8)
-
-#define MXC_SRPG_EMPGC1_SRPGCR	(MXC_SRPG_EMPGC1_BASE + 0x0)
-#define MXC_SRPG_EMPGC1_PUPSCR	(MXC_SRPG_EMPGC1_BASE + 0x4)
-#define MXC_SRPG_EMPGC1_PDNSCR	(MXC_SRPG_EMPGC1_BASE + 0x8)
-
-#define MXC_SRPG_MEGAMIX_SRPGCR		(MXC_SRPG_MEGAMIX_BASE + 0x0)
-#define MXC_SRPG_MEGAMIX_PUPSCR		(MXC_SRPG_MEGAMIX_BASE + 0x4)
-#define MXC_SRPG_MEGAMIX_PDNSCR		(MXC_SRPG_MEGAMIX_BASE + 0x8)
-
-#define MXC_SRPGC_EMI_SRPGCR	(MXC_SRPGC_EMI_BASE + 0x0)
-#define MXC_SRPGC_EMI_PUPSCR	(MXC_SRPGC_EMI_BASE + 0x4)
-#define MXC_SRPGC_EMI_PDNSCR	(MXC_SRPGC_EMI_BASE + 0x8)
-
-#endif				/* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
diff --git a/arch/arm/mach-mx5/devices-imx50.h b/arch/arm/mach-mx5/devices-imx50.h
deleted file mode 100644
index 7216667..0000000
--- a/arch/arm/mach-mx5/devices-imx50.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <mach/mx50.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
-#define imx50_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
-
-extern const struct imx_fec_data imx50_fec_data;
-#define imx50_add_fec(pdata)	\
-	imx_add_fec(&imx50_fec_data, pdata)
-
-extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
-#define imx50_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
deleted file mode 100644
index af488bc..0000000
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx51.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx51_fec_data;
-#define imx51_add_fec(pdata)	\
-	imx_add_fec(&imx51_fec_data, pdata)
-
-extern const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data;
-#define imx51_add_fsl_usb2_udc(pdata)	\
-	imx_add_fsl_usb2_udc(&imx51_fsl_usb2_udc_data, pdata)
-
-extern const struct imx_imx_i2c_data imx51_imx_i2c_data[];
-#define imx51_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx51_imx_i2c_data[id], pdata)
-#define imx51_add_hsi2c(pdata)	\
-	imx51_add_imx_i2c(2, pdata)
-
-extern const struct imx_imx_ssi_data imx51_imx_ssi_data[];
-#define imx51_add_imx_ssi(id, pdata)	\
-	imx_add_imx_ssi(&imx51_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_uart_1irq_data imx51_imx_uart_data[];
-#define imx51_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx51_imx_uart_data[id], pdata)
-
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_otg_data;
-#define imx51_add_mxc_ehci_otg(pdata)	\
-	imx_add_mxc_ehci(&imx51_mxc_ehci_otg_data, pdata)
-extern const struct imx_mxc_ehci_data imx51_mxc_ehci_hs_data[];
-#define imx51_add_mxc_ehci_hs(id, pdata)	\
-	imx_add_mxc_ehci(&imx51_mxc_ehci_hs_data[id - 1], pdata)
-
-extern const struct imx_mxc_nand_data imx51_mxc_nand_data;
-#define imx51_add_mxc_nand(pdata)	\
-	imx_add_mxc_nand(&imx51_mxc_nand_data, pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx51_sdhci_esdhc_imx_data[];
-#define imx51_add_sdhci_esdhc_imx(id, pdata)	\
-	imx_add_sdhci_esdhc_imx(&imx51_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx51_cspi_data;
-#define imx51_add_cspi(pdata)	\
-	imx_add_spi_imx(&imx51_cspi_data, pdata)
-
-extern const struct imx_spi_imx_data imx51_ecspi_data[];
-#define imx51_add_ecspi(id, pdata)	\
-	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id, pdata)	\
-	imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
-
-extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
-#define imx51_add_mxc_pwm(id)	\
-	imx_add_mxc_pwm(&imx51_mxc_pwm_data[id])
-
-extern const struct imx_imx_keypad_data imx51_imx_keypad_data;
-#define imx51_add_imx_keypad(pdata)	\
-	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx51_pata_imx_data;
-#define imx51_add_pata_imx() \
-	imx_add_pata_imx(&imx51_pata_imx_data)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
deleted file mode 100644
index 6e1e5d1..0000000
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@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 <mach/mx53.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx53_fec_data;
-#define imx53_add_fec(pdata)   \
-	imx_add_fec(&imx53_fec_data, pdata)
-
-extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
-#define imx53_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
-
-
-extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
-#define imx53_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
-#define imx53_add_sdhci_esdhc_imx(id, pdata)	\
-	imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx53_ecspi_data[];
-#define imx53_add_ecspi(id, pdata)	\
-	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id, pdata)	\
-	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
-
-extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
-#define imx53_add_imx_ssi(id, pdata)	\
-	imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
-#define imx53_add_imx_keypad(pdata)	\
-	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx53_pata_imx_data;
-#define imx53_add_pata_imx() \
-	imx_add_pata_imx(&imx53_pata_imx_data)
-
-extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-mx5/efika.h b/arch/arm/mach-mx5/efika.h
deleted file mode 100644
index 014aa98..0000000
--- a/arch/arm/mach-mx5/efika.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _EFIKA_H
-#define _EFIKA_H
-
-#define EFIKA_WLAN_EN		IMX_GPIO_NR(2, 16)
-#define EFIKA_WLAN_RESET	IMX_GPIO_NR(2, 10)
-#define EFIKA_USB_PHY_RESET	IMX_GPIO_NR(2, 9)
-
-void __init efika_board_common_init(void);
-
-#endif
diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c
deleted file mode 100644
index c17fa13..0000000
--- a/arch/arm/mach-mx5/ehci.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
-
-#define MXC_OTG_OFFSET			0
-#define MXC_H1_OFFSET			0x200
-#define MXC_H2_OFFSET			0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT		(1 << 5)	/* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
-
-#define MXC_USBCMD_OFFSET		0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
-
-int mx51_initialize_usb_hw(int port, unsigned int flags)
-{
-	unsigned int v;
-	void __iomem *usb_base;
-	void __iomem *usbotg_base;
-	void __iomem *usbother_base;
-	int ret = 0;
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base) {
-		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	switch (port) {
-	case 0:	/* OTG port */
-		usbotg_base = usb_base + MXC_OTG_OFFSET;
-		break;
-	case 1:	/* Host 1 port */
-		usbotg_base = usb_base + MXC_H1_OFFSET;
-		break;
-	case 2: /* Host 2 port */
-		usbotg_base = usb_base + MXC_H2_OFFSET;
-		break;
-	default:
-		printk(KERN_ERR"%s no such port %d\n", __func__, port);
-		ret = -ENOENT;
-		goto error;
-	}
-	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-	switch (port) {
-	case 0:	/*OTG port */
-		if (flags & MXC_EHCI_INTERNAL_PHY) {
-			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-				/* OC/USBPWR is not used */
-				v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-			} else {
-				/* OC/USBPWR is used */
-				v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-			}
-			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED)
-				v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-			else
-				v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v |= MXC_OTG_UCTRL_OPM_BIT;
-			else
-				v &= ~MXC_OTG_UCTRL_OPM_BIT;
-			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-		}
-		break;
-	case 1:	/* Host 1 */
-		/*Host ULPI */
-		v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-			/* HOST1 wakeup/ULPI intr enable */
-			v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-		} else {
-			/* HOST1 wakeup/ULPI intr disable */
-			v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-		}
-
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-		else
-			v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-		__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-		v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-		else
-			v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-		__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-		v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-		if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-			/* Interrupt Threshold Control:Immediate (no threshold) */
-			v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-		__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-		break;
-	case 2: /* Host 2 ULPI */
-		v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-			/* HOST1 wakeup/ULPI intr enable */
-			v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-		} else {
-			/* HOST1 wakeup/ULPI intr disable */
-			v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-		}
-
-		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-			v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-		else
-			v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-		__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-		break;
-	}
-
-error:
-	iounmap(usb_base);
-	return ret;
-}
-
diff --git a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
deleted file mode 100644
index a6a3ab8..0000000
--- a/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Eric Bénard <eric@eukrea.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/i2c/tsc2007.h>
-#include <linux/leds.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/mach/arch.h>
-
-#include "devices-imx51.h"
-
-#define MBIMX51_TSC2007_GPIO	IMX_GPIO_NR(3, 30)
-#define MBIMX51_LED0		IMX_GPIO_NR(3, 5)
-#define MBIMX51_LED1		IMX_GPIO_NR(3, 6)
-#define MBIMX51_LED2		IMX_GPIO_NR(3, 7)
-#define MBIMX51_LED3		IMX_GPIO_NR(3, 8)
-
-static const struct gpio_led mbimx51_leds[] __initconst = {
-	{
-		.name			= "led0",
-		.default_trigger	= "heartbeat",
-		.active_low		= 1,
-		.gpio			= MBIMX51_LED0,
-	},
-	{
-		.name			= "led1",
-		.default_trigger	= "nand-disk",
-		.active_low		= 1,
-		.gpio			= MBIMX51_LED1,
-	},
-	{
-		.name			= "led2",
-		.default_trigger	= "mmc0",
-		.active_low		= 1,
-		.gpio			= MBIMX51_LED2,
-	},
-	{
-		.name			= "led3",
-		.default_trigger	= "default-on",
-		.active_low		= 1,
-		.gpio			= MBIMX51_LED3,
-	},
-};
-
-static const struct gpio_led_platform_data mbimx51_leds_info __initconst = {
-	.leds		= mbimx51_leds,
-	.num_leds	= ARRAY_SIZE(mbimx51_leds),
-};
-
-static iomux_v3_cfg_t mbimx51_pads[] = {
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-
-	/* UART3 */
-	MX51_PAD_UART3_RXD__UART3_RXD,
-	MX51_PAD_UART3_TXD__UART3_TXD,
-	MX51_PAD_KEY_COL4__UART3_RTS,
-	MX51_PAD_KEY_COL5__UART3_CTS,
-
-	/* TSC2007 IRQ */
-	MX51_PAD_NANDF_D10__GPIO3_30,
-
-	/* LEDS */
-	MX51_PAD_DISPB2_SER_DIN__GPIO3_5,
-	MX51_PAD_DISPB2_SER_DIO__GPIO3_6,
-	MX51_PAD_DISPB2_SER_CLK__GPIO3_7,
-	MX51_PAD_DISPB2_SER_RS__GPIO3_8,
-
-	/* KPP */
-	MX51_PAD_KEY_ROW0__KEY_ROW0,
-	MX51_PAD_KEY_ROW1__KEY_ROW1,
-	MX51_PAD_KEY_ROW2__KEY_ROW2,
-	MX51_PAD_KEY_ROW3__KEY_ROW3,
-	MX51_PAD_KEY_COL0__KEY_COL0,
-	MX51_PAD_KEY_COL1__KEY_COL1,
-	MX51_PAD_KEY_COL2__KEY_COL2,
-	MX51_PAD_KEY_COL3__KEY_COL3,
-
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mbimx51_keymap[] = {
-	KEY(0, 0, KEY_1),
-	KEY(0, 1, KEY_2),
-	KEY(0, 2, KEY_3),
-	KEY(0, 3, KEY_UP),
-
-	KEY(1, 0, KEY_4),
-	KEY(1, 1, KEY_5),
-	KEY(1, 2, KEY_6),
-	KEY(1, 3, KEY_LEFT),
-
-	KEY(2, 0, KEY_7),
-	KEY(2, 1, KEY_8),
-	KEY(2, 2, KEY_9),
-	KEY(2, 3, KEY_RIGHT),
-
-	KEY(3, 0, KEY_0),
-	KEY(3, 1, KEY_DOWN),
-	KEY(3, 2, KEY_ESC),
-	KEY(3, 3, KEY_ENTER),
-};
-
-static const struct matrix_keymap_data mbimx51_map_data __initconst = {
-	.keymap		= mbimx51_keymap,
-	.keymap_size	= ARRAY_SIZE(mbimx51_keymap),
-};
-
-static int tsc2007_get_pendown_state(void)
-{
-	return !gpio_get_value(MBIMX51_TSC2007_GPIO);
-}
-
-struct tsc2007_platform_data tsc2007_data = {
-	.model = 2007,
-	.x_plate_ohms = 180,
-	.get_pendown_state = tsc2007_get_pendown_state,
-};
-
-static struct i2c_board_info mbimx51_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("tsc2007", 0x49),
-		.irq  = IMX_GPIO_TO_IRQ(MBIMX51_TSC2007_GPIO),
-		.platform_data = &tsc2007_data,
-	}, {
-		I2C_BOARD_INFO("tlv320aic23", 0x1a),
-	},
-};
-
-/*
- * baseboard initialization.
- */
-void __init eukrea_mbimx51_baseboard_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mbimx51_pads,
-					ARRAY_SIZE(mbimx51_pads));
-
-	imx51_add_imx_uart(1, NULL);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	gpio_request(MBIMX51_LED0, "LED0");
-	gpio_direction_output(MBIMX51_LED0, 1);
-	gpio_free(MBIMX51_LED0);
-	gpio_request(MBIMX51_LED1, "LED1");
-	gpio_direction_output(MBIMX51_LED1, 1);
-	gpio_free(MBIMX51_LED1);
-	gpio_request(MBIMX51_LED2, "LED2");
-	gpio_direction_output(MBIMX51_LED2, 1);
-	gpio_free(MBIMX51_LED2);
-	gpio_request(MBIMX51_LED3, "LED3");
-	gpio_direction_output(MBIMX51_LED3, 1);
-	gpio_free(MBIMX51_LED3);
-
-	gpio_led_register_device(-1, &mbimx51_leds_info);
-
-	imx51_add_imx_keypad(&mbimx51_map_data);
-
-	gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
-	gpio_direction_input(MBIMX51_TSC2007_GPIO);
-	irq_set_irq_type(gpio_to_irq(MBIMX51_TSC2007_GPIO),
-					IRQF_TRIGGER_FALLING);
-	i2c_register_board_info(1, mbimx51_i2c_devices,
-				ARRAY_SIZE(mbimx51_i2c_devices));
-
-	imx51_add_sdhci_esdhc_imx(0, NULL);
-	imx51_add_sdhci_esdhc_imx(1, NULL);
-}
diff --git a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
deleted file mode 100644
index d817fc8..0000000
--- a/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2010 Eric Benard - eric@eukrea.com
- *
- * Based on pcm970-baseboard.c which is :
- * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/iomux-mx51.h>
-#include <mach/audmux.h>
-
-#include "devices-imx51.h"
-
-static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
-	/* LED */
-	MX51_PAD_NANDF_D10__GPIO3_30,
-	/* SWITCH */
-	NEW_PAD_CTRL(MX51_PAD_NANDF_D9__GPIO3_31, PAD_CTL_PUS_22K_UP |
-			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-	/* UART 3 */
-	MX51_PAD_UART3_RXD__UART3_RXD,
-	MX51_PAD_UART3_TXD__UART3_TXD,
-	MX51_PAD_KEY_COL4__UART3_RTS,
-	MX51_PAD_KEY_COL5__UART3_CTS,
-	/* SD */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-	/* SD1 CD */
-	NEW_PAD_CTRL(MX51_PAD_GPIO1_0__SD1_CD, PAD_CTL_PUS_22K_UP |
-			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
-			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
-};
-
-#define GPIO_LED1	IMX_GPIO_NR(3, 30)
-#define GPIO_SWITCH1	IMX_GPIO_NR(3, 31)
-
-static const struct gpio_led eukrea_mbimxsd_leds[] __initconst = {
-	{
-		.name			= "led1",
-		.default_trigger	= "heartbeat",
-		.active_low		= 1,
-		.gpio			= GPIO_LED1,
-	},
-};
-
-static const struct gpio_led_platform_data
-		eukrea_mbimxsd_led_info __initconst = {
-	.leds		= eukrea_mbimxsd_leds,
-	.num_leds	= ARRAY_SIZE(eukrea_mbimxsd_leds),
-};
-
-static struct gpio_keys_button eukrea_mbimxsd_gpio_buttons[] = {
-	{
-		.gpio		= GPIO_SWITCH1,
-		.code		= BTN_0,
-		.desc		= "BP1",
-		.active_low	= 1,
-		.wakeup		= 1,
-	},
-};
-
-static const struct gpio_keys_platform_data
-		eukrea_mbimxsd_button_data __initconst = {
-	.buttons	= eukrea_mbimxsd_gpio_buttons,
-	.nbuttons	= ARRAY_SIZE(eukrea_mbimxsd_gpio_buttons),
-};
-
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static struct i2c_board_info eukrea_mbimxsd_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("tlv320aic23", 0x1a),
-	},
-};
-
-/*
- * system init for baseboard usage. Will be called by cpuimx51sd init.
- *
- * Add platform devices present on this baseboard and init
- * them from CPU side as far as required to use them later on
- */
-void __init eukrea_mbimxsd51_baseboard_init(void)
-{
-	if (mxc_iomux_v3_setup_multiple_pads(eukrea_mbimxsd_pads,
-			ARRAY_SIZE(eukrea_mbimxsd_pads)))
-		printk(KERN_ERR "error setting mbimxsd pads !\n");
-
-	imx51_add_imx_uart(1, NULL);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	imx51_add_sdhci_esdhc_imx(0, NULL);
-
-	gpio_request(GPIO_LED1, "LED1");
-	gpio_direction_output(GPIO_LED1, 1);
-	gpio_free(GPIO_LED1);
-
-	gpio_request(GPIO_SWITCH1, "SWITCH1");
-	gpio_direction_input(GPIO_SWITCH1);
-	gpio_free(GPIO_SWITCH1);
-
-	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
-				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
-
-	gpio_led_register_device(-1, &eukrea_mbimxsd_led_info);
-	imx_add_gpio_keys(&eukrea_mbimxsd_button_data);
-}
diff --git a/arch/arm/mach-mx5/imx51-dt.c b/arch/arm/mach-mx5/imx51-dt.c
deleted file mode 100644
index e6bad17..0000000
--- a/arch/arm/mach-mx5/imx51-dt.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx51.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-uart", MX51_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-fec", MX51_FEC_BASE_ADDR, "imx27-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx51.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx51.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx51.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-esdhc", MX51_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx51.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-ecspi", MX51_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-cspi", MX51_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-i2c", MX51_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-sdma", MX51_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-	OF_DEV_AUXDATA("fsl,imx51-wdt", MX51_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-	{ /* sentinel */ }
-};
-
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
-{
-	irq_domain_add_simple(np, 0);
-	return 0;
-}
-
-static int __init imx51_gpio_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
-{
-	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-	gpio_irq_base -= 32;
-	irq_domain_add_simple(np, gpio_irq_base);
-
-	return 0;
-}
-
-static const struct of_device_id imx51_irq_match[] __initconst = {
-	{ .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
-	{ .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
-	{ /* sentinel */ }
-};
-
-static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
-	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
-	{ /* sentinel */ }
-};
-
-static void __init imx51_dt_init(void)
-{
-	struct device_node *node;
-	const struct of_device_id *of_id;
-	void (*func)(void);
-
-	of_irq_init(imx51_irq_match);
-
-	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
-	if (node) {
-		of_id = of_match_node(imx51_iomuxc_of_match, node);
-		func = of_id->data;
-		func();
-		of_node_put(node);
-	}
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx51_auxdata_lookup, NULL);
-}
-
-static void __init imx51_timer_init(void)
-{
-	mx51_clocks_init_dt();
-}
-
-static struct sys_timer imx51_timer = {
-	.init = imx51_timer_init,
-};
-
-static const char *imx51_dt_board_compat[] __initdata = {
-	"fsl,imx51-babbage",
-	NULL
-};
-
-DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
-	.map_io		= mx51_map_io,
-	.init_early	= imx51_init_early,
-	.init_irq	= mx51_init_irq,
-	.handle_irq	= imx51_handle_irq,
-	.timer		= &imx51_timer,
-	.init_machine	= imx51_dt_init,
-	.dt_compat	= imx51_dt_board_compat,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/imx53-dt.c b/arch/arm/mach-mx5/imx53-dt.c
deleted file mode 100644
index 05ebb3e..0000000
--- a/arch/arm/mach-mx5/imx53-dt.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * 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/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-	{ /* sentinel */ }
-};
-
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
-{
-	irq_domain_add_simple(np, 0);
-	return 0;
-}
-
-static int __init imx53_gpio_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
-{
-	static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-	gpio_irq_base -= 32;
-	irq_domain_add_simple(np, gpio_irq_base);
-
-	return 0;
-}
-
-static const struct of_device_id imx53_irq_match[] __initconst = {
-	{ .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
-	{ .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
-	{ /* sentinel */ }
-};
-
-static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
-	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
-	{ /* sentinel */ }
-};
-
-static void __init imx53_dt_init(void)
-{
-	struct device_node *node;
-	const struct of_device_id *of_id;
-	void (*func)(void);
-
-	of_irq_init(imx53_irq_match);
-
-	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
-	if (node) {
-		of_id = of_match_node(imx53_iomuxc_of_match, node);
-		func = of_id->data;
-		func();
-		of_node_put(node);
-	}
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx53_auxdata_lookup, NULL);
-}
-
-static void __init imx53_timer_init(void)
-{
-	mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
-	.init = imx53_timer_init,
-};
-
-static const char *imx53_dt_board_compat[] __initdata = {
-	"fsl,imx53-ard",
-	"fsl,imx53-evk",
-	"fsl,imx53-qsb",
-	"fsl,imx53-smd",
-	NULL
-};
-
-DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
-	.map_io		= mx53_map_io,
-	.init_early	= imx53_init_early,
-	.init_irq	= mx53_init_irq,
-	.handle_irq	= imx53_handle_irq,
-	.timer		= &imx53_timer,
-	.init_machine	= imx53_dt_init,
-	.dt_compat	= imx53_dt_board_compat,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
deleted file mode 100644
index bc17dfe..0000000
--- a/arch/arm/mach-mx5/mm.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License.  You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- *
- * Create static mapping between physical to virtual memory.
- */
-
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/devices-common.h>
-#include <mach/iomux-v3.h>
-
-static struct clk *gpc_dvfs_clk;
-
-static void imx5_idle(void)
-{
-	if (!need_resched()) {
-		/* gpc clock is needed for SRPG */
-		if (gpc_dvfs_clk == NULL) {
-			gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-			if (IS_ERR(gpc_dvfs_clk))
-				goto err0;
-		}
-		clk_enable(gpc_dvfs_clk);
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-		if (tzic_enable_wake())
-			goto err1;
-		cpu_do_idle();
-err1:
-		clk_disable(gpc_dvfs_clk);
-	}
-err0:
-	local_irq_enable();
-}
-
-/*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-	imx_map_entry(MX50, TZIC, MT_DEVICE),
-	imx_map_entry(MX50, SPBA0, MT_DEVICE),
-	imx_map_entry(MX50, AIPS1, MT_DEVICE),
-	imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX51 memory map.
- */
-static struct map_desc mx51_io_desc[] __initdata = {
-	imx_map_entry(MX51, TZIC, MT_DEVICE),
-	imx_map_entry(MX51, IRAM, MT_DEVICE),
-	imx_map_entry(MX51, AIPS1, MT_DEVICE),
-	imx_map_entry(MX51, SPBA0, MT_DEVICE),
-	imx_map_entry(MX51, AIPS2, MT_DEVICE),
-};
-
-/*
- * Define the MX53 memory map.
- */
-static struct map_desc mx53_io_desc[] __initdata = {
-	imx_map_entry(MX53, TZIC, MT_DEVICE),
-	imx_map_entry(MX53, AIPS1, MT_DEVICE),
-	imx_map_entry(MX53, SPBA0, MT_DEVICE),
-	imx_map_entry(MX53, AIPS2, MT_DEVICE),
-};
-
-/*
- * This function initializes the memory map. It is called during the
- * system startup to create static physical to virtual memory mappings
- * for the IO modules.
- */
-void __init mx50_map_io(void)
-{
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
-void __init mx51_map_io(void)
-{
-	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
-}
-
-void __init mx53_map_io(void)
-{
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
-}
-
-void __init imx50_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX50);
-	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
-void __init imx51_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX51);
-	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-	pm_idle = imx5_idle;
-}
-
-void __init imx53_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX53);
-	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
-}
-
-void __init mx50_init_irq(void)
-{
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
-void __init mx51_init_irq(void)
-{
-	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
-}
-
-void __init mx53_init_irq(void)
-{
-	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
-}
-
-static struct sdma_script_start_addrs imx51_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.uart_2_mcu_addr = 817,
-	.mcu_2_app_addr = 747,
-	.mcu_2_shp_addr = 961,
-	.ata_2_mcu_addr = 1473,
-	.mcu_2_ata_addr = 1392,
-	.app_2_per_addr = 1033,
-	.app_2_mcu_addr = 683,
-	.shp_2_per_addr = 1251,
-	.shp_2_mcu_addr = 892,
-};
-
-static struct sdma_platform_data imx51_sdma_pdata __initdata = {
-	.fw_name = "sdma-imx51.bin",
-	.script_addrs = &imx51_sdma_script,
-};
-
-static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.app_2_mcu_addr = 683,
-	.mcu_2_app_addr = 747,
-	.uart_2_mcu_addr = 817,
-	.shp_2_mcu_addr = 891,
-	.mcu_2_shp_addr = 960,
-	.uartsh_2_mcu_addr = 1032,
-	.spdif_2_mcu_addr = 1100,
-	.mcu_2_spdif_addr = 1134,
-	.firi_2_mcu_addr = 1193,
-	.mcu_2_firi_addr = 1290,
-};
-
-static struct sdma_platform_data imx53_sdma_pdata __initdata = {
-	.fw_name = "sdma-imx53.bin",
-	.script_addrs = &imx53_sdma_script,
-};
-
-void __init imx50_soc_init(void)
-{
-	/* i.mx50 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx31-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx31-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-}
-
-void __init imx51_soc_init(void)
-{
-	/* i.mx51 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX51_GPIO1_BASE_ADDR, SZ_16K, MX51_INT_GPIO1_LOW, MX51_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX51_GPIO2_BASE_ADDR, SZ_16K, MX51_INT_GPIO2_LOW, MX51_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX51_GPIO3_BASE_ADDR, SZ_16K, MX51_INT_GPIO3_LOW, MX51_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX51_GPIO4_BASE_ADDR, SZ_16K, MX51_INT_GPIO4_LOW, MX51_INT_GPIO4_HIGH);
-
-	/* i.mx51 has the i.mx35 type sdma */
-	imx_add_imx_sdma("imx35-sdma", MX51_SDMA_BASE_ADDR, MX51_INT_SDMA, &imx51_sdma_pdata);
-}
-
-void __init imx53_soc_init(void)
-{
-	/* i.mx53 has the i.mx31 type gpio */
-	mxc_register_gpio("imx31-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx31-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx31-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx31-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx31-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx31-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
-	mxc_register_gpio("imx31-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
-
-	/* i.mx53 has the i.mx35 type sdma */
-	imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
-}
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
deleted file mode 100644
index ec6ca91..0000000
--- a/arch/arm/mach-mx5/mx51_efika.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-#include "cpu_op-mx51.h"
-
-#define MX51_USB_CTRL_1_OFFSET          0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-
-#define EFIKAMX_USB_HUB_RESET	IMX_GPIO_NR(1, 5)
-#define EFIKAMX_USBH1_STP	IMX_GPIO_NR(1, 27)
-
-#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
-
-#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
-
-static iomux_v3_cfg_t mx51efika_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-
-	/* SD/MMC WP/CD */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-	MX51_PAD_GPIO1_7__SD2_WP,
-	MX51_PAD_GPIO1_8__SD2_CD,
-
-	/* spi */
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_GPIO1_6__GPIO1_6,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-	/* USB HUB RESET */
-	MX51_PAD_GPIO1_5__GPIO1_5,
-
-	/* WLAN */
-	MX51_PAD_EIM_A22__GPIO2_16,
-	MX51_PAD_EIM_A16__GPIO2_10,
-
-	/* USB PHY RESET */
-	MX51_PAD_EIM_D27__GPIO2_9,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init   = initialize_otg_port,
-	.portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *socregs_base;
-
-	mxc_iomux_v3_setup_pad(usbh1gpio);
-	gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
-	gpio_direction_output(EFIKAMX_USBH1_STP, 0);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USBH1_STP, 1);
-	msleep(1);
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* The clock for the USBH1 ULPI port will come externally */
-	/* from the PHY. */
-	v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
-			socregs_base + MX51_USB_CTRL_1_OFFSET);
-
-	iounmap(usb_base);
-
-	gpio_free(EFIKAMX_USBH1_STP);
-	mxc_iomux_v3_setup_pad(usbh1stp);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh1_config __initdata = {
-	.init   = initialize_usbh1_port,
-	.portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void mx51_efika_hubreset(void)
-{
-	gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
-	gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
-}
-
-static void __init mx51_efika_usb(void)
-{
-	mx51_efika_hubreset();
-
-	/* pulling it low, means no USB at all... */
-	gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
-	gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
-	msleep(1);
-	gpio_set_value(EFIKA_USB_PHY_RESET, 1);
-
-	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-
-	imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	if (usbh1_config.otg)
-		imx51_add_mxc_ehci_hs(1, &usbh1_config);
-}
-
-static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
-	{
-	 .name = "u-boot",
-	 .offset = 0,
-	 .size = SZ_256K,
-	},
-	{
-	  .name = "config",
-	  .offset = MTDPART_OFS_APPEND,
-	  .size = SZ_64K,
-	},
-};
-
-static struct flash_platform_data mx51_efika_spi_flash_data = {
-	.name		= "spi_flash",
-	.parts		= mx51_efika_spi_nor_partitions,
-	.nr_parts	= ARRAY_SIZE(mx51_efika_spi_nor_partitions),
-	.type		= "sst25vf032b",
-};
-
-static struct regulator_consumer_supply sw1_consumers[] = {
-	{
-		.supply = "cpu_vcc",
-	}
-};
-
-static struct regulator_consumer_supply vdig_consumers[] = {
-	/* sgtl5000 */
-	REGULATOR_SUPPLY("VDDA", "1-000a"),
-	REGULATOR_SUPPLY("VDDD", "1-000a"),
-};
-
-static struct regulator_consumer_supply vvideo_consumers[] = {
-	/* sgtl5000 */
-	REGULATOR_SUPPLY("VDDIO", "1-000a"),
-};
-
-static struct regulator_consumer_supply vsd_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
-};
-
-static struct regulator_consumer_supply pwgt1_consumer[] = {
-	{
-		.supply = "pwgt1",
-	}
-};
-
-static struct regulator_consumer_supply pwgt2_consumer[] = {
-	{
-		.supply = "pwgt2",
-	}
-};
-
-static struct regulator_consumer_supply coincell_consumer[] = {
-	{
-		.supply = "coincell",
-	}
-};
-
-static struct regulator_init_data sw1_init = {
-	.constraints = {
-		.name = "SW1",
-		.min_uV = 600000,
-		.max_uV = 1375000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.valid_modes_mask = 0,
-		.always_on = 1,
-		.boot_on = 1,
-		.state_mem = {
-			.uV = 850000,
-			.mode = REGULATOR_MODE_NORMAL,
-			.enabled = 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
-	.consumer_supplies = sw1_consumers,
-};
-
-static struct regulator_init_data sw2_init = {
-	.constraints = {
-		.name = "SW2",
-		.min_uV = 900000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-		.state_mem = {
-			.uV = 950000,
-			.mode = REGULATOR_MODE_NORMAL,
-			.enabled = 1,
-		},
-	}
-};
-
-static struct regulator_init_data sw3_init = {
-	.constraints = {
-		.name = "SW3",
-		.min_uV = 1100000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data sw4_init = {
-	.constraints = {
-		.name = "SW4",
-		.min_uV = 1100000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data viohi_init = {
-	.constraints = {
-		.name = "VIOHI",
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vusb_init = {
-	.constraints = {
-		.name = "VUSB",
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data swbst_init = {
-	.constraints = {
-		.name = "SWBST",
-	}
-};
-
-static struct regulator_init_data vdig_init = {
-	.constraints = {
-		.name = "VDIG",
-		.min_uV = 1050000,
-		.max_uV = 1800000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
-	.consumer_supplies = vdig_consumers,
-};
-
-static struct regulator_init_data vpll_init = {
-	.constraints = {
-		.name = "VPLL",
-		.min_uV = 1050000,
-		.max_uV = 1800000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vusb2_init = {
-	.constraints = {
-		.name = "VUSB2",
-		.min_uV = 2400000,
-		.max_uV = 2775000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vvideo_init = {
-	.constraints = {
-		.name = "VVIDEO",
-		.min_uV = 2775000,
-		.max_uV = 2775000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.apply_uV = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
-	.consumer_supplies = vvideo_consumers,
-};
-
-static struct regulator_init_data vaudio_init = {
-	.constraints = {
-		.name = "VAUDIO",
-		.min_uV = 2300000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data vsd_init = {
-	.constraints = {
-		.name = "VSD",
-		.min_uV = 1800000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE,
-		.boot_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
-	.consumer_supplies = vsd_consumers,
-};
-
-static struct regulator_init_data vcam_init = {
-	.constraints = {
-		.name = "VCAM",
-		.min_uV = 2500000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen1_init = {
-	.constraints = {
-		.name = "VGEN1",
-		.min_uV = 1200000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen2_init = {
-	.constraints = {
-		.name = "VGEN2",
-		.min_uV = 1200000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen3_init = {
-	.constraints = {
-		.name = "VGEN3",
-		.min_uV = 1800000,
-		.max_uV = 2900000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data gpo1_init = {
-	.constraints = {
-		.name = "GPO1",
-	}
-};
-
-static struct regulator_init_data gpo2_init = {
-	.constraints = {
-		.name = "GPO2",
-	}
-};
-
-static struct regulator_init_data gpo3_init = {
-	.constraints = {
-		.name = "GPO3",
-	}
-};
-
-static struct regulator_init_data gpo4_init = {
-	.constraints = {
-		.name = "GPO4",
-	}
-};
-
-static struct regulator_init_data pwgt1_init = {
-	.constraints = {
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on        = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
-	.consumer_supplies = pwgt1_consumer,
-};
-
-static struct regulator_init_data pwgt2_init = {
-	.constraints = {
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on        = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
-	.consumer_supplies = pwgt2_consumer,
-};
-
-static struct regulator_init_data vcoincell_init = {
-	.constraints = {
-		.name = "COINCELL",
-		.min_uV = 3000000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
-	.consumer_supplies = coincell_consumer,
-};
-
-static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
-	{ .id = MC13892_SW1,		.init_data =  &sw1_init },
-	{ .id = MC13892_SW2,		.init_data =  &sw2_init },
-	{ .id = MC13892_SW3,		.init_data =  &sw3_init },
-	{ .id = MC13892_SW4,		.init_data =  &sw4_init },
-	{ .id = MC13892_SWBST,		.init_data =  &swbst_init },
-	{ .id = MC13892_VIOHI,		.init_data =  &viohi_init },
-	{ .id = MC13892_VPLL,		.init_data =  &vpll_init },
-	{ .id = MC13892_VDIG,		.init_data =  &vdig_init },
-	{ .id = MC13892_VSD,		.init_data =  &vsd_init },
-	{ .id = MC13892_VUSB2,		.init_data =  &vusb2_init },
-	{ .id = MC13892_VVIDEO,		.init_data =  &vvideo_init },
-	{ .id = MC13892_VAUDIO,		.init_data =  &vaudio_init },
-	{ .id = MC13892_VCAM,		.init_data =  &vcam_init },
-	{ .id = MC13892_VGEN1,		.init_data =  &vgen1_init },
-	{ .id = MC13892_VGEN2,		.init_data =  &vgen2_init },
-	{ .id = MC13892_VGEN3,		.init_data =  &vgen3_init },
-	{ .id = MC13892_VUSB,		.init_data =  &vusb_init },
-	{ .id = MC13892_GPO1,		.init_data =  &gpo1_init },
-	{ .id = MC13892_GPO2,		.init_data =  &gpo2_init },
-	{ .id = MC13892_GPO3,		.init_data =  &gpo3_init },
-	{ .id = MC13892_GPO4,		.init_data =  &gpo4_init },
-	{ .id = MC13892_PWGT1SPI,	.init_data = &pwgt1_init },
-	{ .id = MC13892_PWGT2SPI,	.init_data = &pwgt2_init },
-	{ .id = MC13892_VCOINCELL,	.init_data = &vcoincell_init },
-};
-
-static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-	.flags = MC13XXX_USE_RTC,
-	.regulators = {
-		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
-		.regulators = mx51_efika_regulators,
-	},
-};
-
-static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
-	{
-		.modalias = "m25p80",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.platform_data = &mx51_efika_spi_flash_data,
-		.irq = -1,
-	},
-	{
-		.modalias = "mc13892",
-		.max_speed_hz = 1000000,
-		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = &mx51_efika_mc13892_data,
-		.irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
-	},
-};
-
-static int mx51_efika_spi_cs[] = {
-	EFIKAMX_SPI_CS0,
-	EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
-	.chipselect     = mx51_efika_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
-};
-
-void __init efika_board_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
-					ARRAY_SIZE(mx51efika_pads));
-	imx51_add_imx_uart(0, &uart_pdata);
-	mx51_efika_usb();
-
-	/* FIXME: comes from original code. check this. */
-	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-		sw2_init.constraints.state_mem.uV = 1100000;
-	else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
-		sw2_init.constraints.state_mem.uV = 1250000;
-		sw1_init.constraints.state_mem.uV = 1000000;
-	}
-	if (machine_is_mx51_efikasb())
-		vgen1_init.constraints.max_uV = 1200000;
-
-	gpio_request(EFIKAMX_PMIC, "pmic irq");
-	gpio_direction_input(EFIKAMX_PMIC);
-	spi_register_board_info(mx51_efika_spi_board_info,
-		ARRAY_SIZE(mx51_efika_spi_board_info));
-	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
-
-	imx51_add_pata_imx();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
-}
diff --git a/arch/arm/mach-mx5/pm-imx5.c b/arch/arm/mach-mx5/pm-imx5.c
deleted file mode 100644
index 98052fc..0000000
--- a/arch/arm/mach-mx5/pm-imx5.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/suspend.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include "crm_regs.h"
-
-static struct clk *gpc_dvfs_clk;
-
-static int mx5_suspend_prepare(void)
-{
-	return clk_enable(gpc_dvfs_clk);
-}
-
-static int mx5_suspend_enter(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_MEM:
-		mx5_cpu_lp_set(STOP_POWER_OFF);
-		break;
-	case PM_SUSPEND_STANDBY:
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (state == PM_SUSPEND_MEM) {
-		local_flush_tlb_all();
-		flush_cache_all();
-
-		/*clear the EMPGC0/1 bits */
-		__raw_writel(0, MXC_SRPG_EMPGC0_SRPGCR);
-		__raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
-	}
-	cpu_do_idle();
-	return 0;
-}
-
-static void mx5_suspend_finish(void)
-{
-	clk_disable(gpc_dvfs_clk);
-}
-
-static int mx5_pm_valid(suspend_state_t state)
-{
-	return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
-}
-
-static const struct platform_suspend_ops mx5_suspend_ops = {
-	.valid = mx5_pm_valid,
-	.prepare = mx5_suspend_prepare,
-	.enter = mx5_suspend_enter,
-	.finish = mx5_suspend_finish,
-};
-
-static int __init mx5_pm_init(void)
-{
-	if (gpc_dvfs_clk == NULL)
-		gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-
-	if (!IS_ERR(gpc_dvfs_clk)) {
-		if (cpu_is_mx51())
-			suspend_set_ops(&mx5_suspend_ops);
-	} else
-		return -EPERM;
-
-	return 0;
-}
-device_initcall(mx5_pm_init);
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
deleted file mode 100644
index 5eebfaa..0000000
--- a/arch/arm/mach-mx5/system.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include "crm_regs.h"
-
-/* set cpu low power mode before WFI instruction. This function is called
-  * mx5 because it can be used for mx50, mx51, and mx53.*/
-void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
-{
-	u32 plat_lpc, arm_srpgcr, ccm_clpcr;
-	u32 empgc0, empgc1;
-	int stop_mode = 0;
-
-	/* always allow platform to issue a deep sleep mode request */
-	plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
-	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
-	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
-	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
-	empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
-	empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
-
-	switch (mode) {
-	case WAIT_CLOCKED:
-		break;
-	case WAIT_UNCLOCKED:
-		ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
-		break;
-	case WAIT_UNCLOCKED_POWER_OFF:
-	case STOP_POWER_OFF:
-		plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
-			    | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
-		if (mode == WAIT_UNCLOCKED_POWER_OFF) {
-			ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
-			ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
-			ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
-			stop_mode = 0;
-		} else {
-			ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
-			ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
-			ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
-			ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
-			stop_mode = 1;
-		}
-		arm_srpgcr |= MXC_SRPGCR_PCR;
-		break;
-	case STOP_POWER_ON:
-		ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
-		break;
-	default:
-		printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
-		return;
-	}
-
-	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
-	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
-	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
-
-	/* Enable NEON SRPG for all but MX50TO1.0. */
-	if (mx50_revision() != IMX_CHIP_REVISION_1_0)
-		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
-
-	if (stop_mode) {
-		empgc0 |= MXC_SRPGCR_PCR;
-		empgc1 |= MXC_SRPGCR_PCR;
-
-		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
-		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
-	}
-}
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 18fd177..5bc1312 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -415,29 +415,9 @@ static struct resource pxa_rtc_resources[] = {
 	},
 };
 
-static struct resource sa1100_rtc_resources[] = {
-	[0] = {
-		.start  = 0x40900000,
-		.end	= 0x409000ff,
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start  = IRQ_RTC1Hz,
-		.end    = IRQ_RTC1Hz,
-		.flags  = IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start  = IRQ_RTCAlrm,
-		.end    = IRQ_RTCAlrm,
-		.flags  = IORESOURCE_IRQ,
-	},
-};
-
 struct platform_device sa1100_device_rtc = {
 	.name		= "sa1100-rtc",
 	.id		= -1,
-	.num_resources  = ARRAY_SIZE(sa1100_rtc_resources),
-	.resource       = sa1100_rtc_resources,
 };
 
 struct platform_device pxa_device_rtc = {
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index adf058f..91e4f6c 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -209,8 +209,6 @@ static struct clk_lookup pxa25x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
 	INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
 	INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
-	INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static struct clk_lookup pxa25x_hwuart_clkreg =
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 180bd86..aed6cbc 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -230,8 +230,6 @@ static struct clk_lookup pxa27x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
 	INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
 	INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
-	INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 #ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
index 0388eda..40bb165 100644
--- a/arch/arm/mach-pxa/pxa300.c
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -89,7 +89,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA300_GCU, 0, 0);
 static struct clk_lookup common_clkregs[] = {
 	INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL),
 	INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0);
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
index d487e1f..8d614ec 100644
--- a/arch/arm/mach-pxa/pxa320.c
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -83,7 +83,6 @@ static DEFINE_PXA3_CKEN(gcu, PXA320_GCU, 0, 0);
 static struct clk_lookup pxa320_clkregs[] = {
 	INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL),
 	INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 };
 
 static int __init pxa320_init(void)
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index f107c71..4f402af 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -67,7 +67,6 @@ static struct clk_lookup pxa3xx_clkregs[] = {
 	INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
 	/* Power I2C clock is always on */
 	INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 	INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
 	INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
 	INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index fccc644..d082a58 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -217,7 +217,6 @@ static struct clk_lookup pxa95x_clkregs[] = {
 	INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
 	/* Power I2C clock is always on */
 	INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
 	INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
 	INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
 	INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c
index 5287d28..5536392 100644
--- a/arch/arm/mach-s3c2416/s3c2416.c
+++ b/arch/arm/mach-s3c2416/s3c2416.c
@@ -60,6 +60,7 @@
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
+#include <plat/rtc-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -101,6 +102,7 @@ int __init s3c2416_init(void)
 	s3c_fb_setname("s3c2443-fb");
 
 	s3c_adc_setname("s3c2416-adc");
+	s3c_rtc_setname("s3c2416-rtc");
 
 #ifdef CONFIG_PM
 	register_syscore_ops(&s3c2416_pm_syscore_ops);
diff --git a/arch/arm/mach-s3c2443/s3c2443.c b/arch/arm/mach-s3c2443/s3c2443.c
index b9deaeb..b7778a9 100644
--- a/arch/arm/mach-s3c2443/s3c2443.c
+++ b/arch/arm/mach-s3c2443/s3c2443.c
@@ -41,6 +41,7 @@
 #include <plat/fb-core.h>
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
+#include <plat/rtc-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
 	IODESC_ENT(WATCHDOG),
@@ -73,6 +74,7 @@ int __init s3c2443_init(void)
 	s3c_fb_setname("s3c2443-fb");
 
 	s3c_adc_setname("s3c2443-adc");
+	s3c_rtc_setname("s3c2443-rtc");
 
 	/* change WDT IRQ number */
 	s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT;
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index dd20c66..dc45123 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -296,5 +296,6 @@ config MACH_WLF_CRAGG_6410
 	select S3C64XX_DEV_SPI0
 	select SAMSUNG_GPIO_EXTRA128
 	select I2C
+	select LEDS_GPIO_REGISTER
 	help
 	  Machine support for the Wolfson Cragganmore S3C6410 variant.
diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile
index 1822ac2..610fe28 100644
--- a/arch/arm/mach-s3c64xx/Makefile
+++ b/arch/arm/mach-s3c64xx/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_CPU_S3C6410)	+= s3c6410.o
 # PM
 
 obj-$(CONFIG_PM)		+= pm.o irq-pm.o sleep.o
+obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 
 # DMA support
 
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 31bb27d..b58274f 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -202,6 +202,15 @@ static struct clk init_clocks_off[] = {
 		.enable		= s3c64xx_sclk_ctrl,
 		.ctrlbit	= S3C_CLKCON_SCLK_MMC2_48,
 	}, {
+		.name		= "ac97",
+		.parent		= &clk_p,
+		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
+	}, {
+		.name		= "cfcon",
+		.parent		= &clk_h,
+		.enable		= s3c64xx_hclk_ctrl,
+		.ctrlbit	= S3C_CLKCON_HCLK_IHOST,
+	}, {
 		.name		= "dma0",
 		.parent		= &clk_h,
 		.enable		= s3c64xx_hclk_ctrl,
@@ -284,16 +293,7 @@ static struct clk init_clocks[] = {
 		.name		= "watchdog",
 		.parent		= &clk_p,
 		.ctrlbit	= S3C_CLKCON_PCLK_WDT,
-	}, {
-		.name		= "ac97",
-		.parent		= &clk_p,
-		.ctrlbit	= S3C_CLKCON_PCLK_AC97,
-	}, {
-		.name		= "cfcon",
-		.parent		= &clk_h,
-		.enable		= s3c64xx_hclk_ctrl,
-		.ctrlbit	= S3C_CLKCON_HCLK_IHOST,
-	}
+	},
 };
 
 static struct clk clk_hsmmc0 = {
diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c
new file mode 100644
index 0000000..179460f
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/cpuidle.c
@@ -0,0 +1,91 @@
+/* linux/arch/arm/mach-s3c64xx/cpuidle.c
+ *
+ * Copyright (c) 2011 Wolfson Microelectronics, plc
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cpuidle.h>
+#include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
+
+#include <asm/proc-fns.h>
+
+#include <mach/map.h>
+
+#include <mach/regs-sys.h>
+#include <mach/regs-syscon-power.h>
+
+static int s3c64xx_enter_idle(struct cpuidle_device *dev,
+			      struct cpuidle_driver *drv,
+			      int index)
+{
+	struct timeval before, after;
+	unsigned long tmp;
+	int idle_time;
+
+	local_irq_disable();
+	do_gettimeofday(&before);
+
+	/* Setup PWRCFG to enter idle mode */
+	tmp = __raw_readl(S3C64XX_PWR_CFG);
+	tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
+	tmp |= S3C64XX_PWRCFG_CFG_WFI_IDLE;
+	__raw_writel(tmp, S3C64XX_PWR_CFG);
+
+	cpu_do_idle();
+
+	do_gettimeofday(&after);
+	local_irq_enable();
+	idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
+		    (after.tv_usec - before.tv_usec);
+
+	dev->last_residency = idle_time;
+	return index;
+}
+
+static struct cpuidle_state s3c64xx_cpuidle_set[] = {
+	[0] = {
+		.enter			= s3c64xx_enter_idle,
+		.exit_latency		= 1,
+		.target_residency	= 1,
+		.flags			= CPUIDLE_FLAG_TIME_VALID,
+		.name			= "IDLE",
+		.desc			= "System active, ARM gated",
+	},
+};
+
+static struct cpuidle_driver s3c64xx_cpuidle_driver = {
+	.name		= "s3c64xx_cpuidle",
+	.owner		= THIS_MODULE,
+	.state_count	= ARRAY_SIZE(s3c64xx_cpuidle_set),
+};
+
+static struct cpuidle_device s3c64xx_cpuidle_device = {
+	.state_count	= ARRAY_SIZE(s3c64xx_cpuidle_set),
+};
+
+static int __init s3c64xx_init_cpuidle(void)
+{
+	int ret;
+
+	memcpy(s3c64xx_cpuidle_driver.states, s3c64xx_cpuidle_set,
+	       sizeof(s3c64xx_cpuidle_set));
+	cpuidle_register_driver(&s3c64xx_cpuidle_driver);
+
+	ret = cpuidle_register_device(&s3c64xx_cpuidle_device);
+	if (ret) {
+		pr_err("Failed to register cpuidle device: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+device_initcall(s3c64xx_init_cpuidle);
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 8077f65..7539a29 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -19,7 +19,9 @@
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/leds.h>
 #include <linux/delay.h>
+#include <linux/mmc/host.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/pwm_backlight.h>
@@ -681,6 +683,7 @@ static void __init crag6410_map_io(void)
 static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = {
 	.max_width		= 4,
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.host_caps		= MMC_CAP_POWER_OFF_CARD,
 };
 
 static void crag6410_cfg_sdhci0(struct platform_device *dev, int width)
@@ -696,6 +699,55 @@ static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = {
 	.max_width		= 4,
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
 	.cfg_gpio		= crag6410_cfg_sdhci0,
+	.host_caps		= MMC_CAP_POWER_OFF_CARD,
+};
+
+static const struct gpio_led gpio_leds[] = {
+	{
+		.name = "d13:green:",
+		.gpio = MMGPIO_GPIO_BASE + 0,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d14:green:",
+		.gpio = MMGPIO_GPIO_BASE + 1,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d15:green:",
+		.gpio = MMGPIO_GPIO_BASE + 2,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d16:green:",
+		.gpio = MMGPIO_GPIO_BASE + 3,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d17:green:",
+		.gpio = MMGPIO_GPIO_BASE + 4,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d18:green:",
+		.gpio = MMGPIO_GPIO_BASE + 5,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d19:green:",
+		.gpio = MMGPIO_GPIO_BASE + 6,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+	{
+		.name = "d20:green:",
+		.gpio = MMGPIO_GPIO_BASE + 7,
+		.default_state = LEDS_GPIO_DEFSTATE_ON,
+	},
+};
+
+static const struct gpio_led_platform_data gpio_leds_pdata = {
+	.leds = gpio_leds,
+	.num_leds = ARRAY_SIZE(gpio_leds),
 };
 
 static void __init crag6410_machine_init(void)
@@ -727,9 +779,12 @@ static void __init crag6410_machine_init(void)
 	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
 	samsung_keypad_set_platdata(&crag6410_keypad_data);
+	s3c64xx_spi0_set_platdata(NULL, 0, 1);
 
 	platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
+	gpio_led_register_device(-1, &gpio_leds_pdata);
+
 	regulator_has_full_constraints();
 
 	s3c64xx_pm_init();
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index d6df9f6..dab3c63 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -11,39 +11,17 @@
 #include <linux/clk.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 
-struct clkops {
-	void			(*enable)(struct clk *);
-	void			(*disable)(struct clk *);
-	unsigned long		(*getrate)(struct clk *);
-};
-
+/*
+ * Very simple clock implementation - we only have one clock to deal with.
+ */
 struct clk {
-	const struct clkops	*ops;
-	unsigned long		rate;
 	unsigned int		enabled;
 };
 
-#define INIT_CLKREG(_clk, _devname, _conname)		\
-	{						\
-		.clk		= _clk,			\
-		.dev_id		= _devname,		\
-		.con_id		= _conname,		\
-	}
-
-#define DEFINE_CLK(_name, _ops, _rate)			\
-struct clk clk_##_name = {				\
-		.ops	= _ops,				\
-		.rate	= _rate,			\
-	}
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void clk_gpio27_enable(struct clk *clk)
+static void clk_gpio27_enable(void)
 {
 	/*
 	 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -54,22 +32,38 @@ static void clk_gpio27_enable(struct clk *clk)
 	TUCR = TUCR_3_6864MHz;
 }
 
-static void clk_gpio27_disable(struct clk *clk)
+static void clk_gpio27_disable(void)
 {
 	TUCR = 0;
 	GPDR &= ~GPIO_32_768kHz;
 	GAFR &= ~GPIO_32_768kHz;
 }
 
+static struct clk clk_gpio27;
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	const char *devname = dev_name(dev);
+
+	return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&clocks_lock, flags);
 	if (clk->enabled++ == 0)
-		clk->ops->enable(clk);
+		clk_gpio27_enable();
 	spin_unlock_irqrestore(&clocks_lock, flags);
-
 	return 0;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -82,48 +76,13 @@ void clk_disable(struct clk *clk)
 
 	spin_lock_irqsave(&clocks_lock, flags);
 	if (--clk->enabled == 0)
-		clk->ops->disable(clk);
+		clk_gpio27_disable();
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
 unsigned long clk_get_rate(struct clk *clk)
 {
-	unsigned long rate;
-
-	rate = clk->rate;
-	if (clk->ops->getrate)
-		rate = clk->ops->getrate(clk);
-
-	return rate;
+	return 3686400;
 }
 EXPORT_SYMBOL(clk_get_rate);
-
-const struct clkops clk_gpio27_ops = {
-	.enable		= clk_gpio27_enable,
-	.disable	= clk_gpio27_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk) { }
-static void clk_dummy_disable(struct clk *clk) { }
-
-const struct clkops clk_dummy_ops = {
-	.enable		= clk_dummy_enable,
-	.disable	= clk_dummy_disable,
-};
-
-static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400);
-static DEFINE_CLK(dummy, &clk_dummy_ops, 0);
-
-static struct clk_lookup sa11xx_clkregs[] = {
-	INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL),
-	INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
-};
-
-static int __init sa11xx_clk_init(void)
-{
-	clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
-	return 0;
-}
-
-postcore_initcall(sa11xx_clk_init);
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index c483912..cce8763 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -144,8 +144,6 @@ static struct pda_power_pdata collie_power_data = {
 static struct resource collie_power_resource[] = {
 	{
 		.name		= "ac",
-		.start		= gpio_to_irq(COLLIE_GPIO_AC_IN),
-		.end		= gpio_to_irq(COLLIE_GPIO_AC_IN),
 		.flags		= IORESOURCE_IRQ |
 				  IORESOURCE_IRQ_HIGHEDGE |
 				  IORESOURCE_IRQ_LOWEDGE,
@@ -347,7 +345,8 @@ static void __init collie_init(void)
 
 	GPSR |= _COLLIE_GPIO_UCB1x00_RESET;
 
-
+	collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
+	collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
 	platform_scoop_config = &collie_pcmcia_config;
 
 	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index aaa8acf..19b2053 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -228,7 +228,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
 	return 0;
 }
 
-static struct cpufreq_driver sa1100_driver = {
+static struct cpufreq_driver sa1100_driver __refdata = {
 	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1100_target,
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index e3a28ca..a7c0df6 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -350,29 +350,9 @@ void sa11x0_register_irda(struct irda_platform_data *irda)
 	sa11x0_register_device(&sa11x0ir_device, irda);
 }
 
-static struct resource sa11x0rtc_resources[] = {
-	[0] = {
-		.start	= 0x90010000,
-		.end	= 0x900100ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_RTC1Hz,
-		.end	= IRQ_RTC1Hz,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= IRQ_RTCAlrm,
-		.end	= IRQ_RTCAlrm,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
 static struct platform_device sa11x0rtc_device = {
 	.name		= "sa1100-rtc",
 	.id		= -1,
-	.resource	= sa11x0rtc_resources,
-	.num_resources	= ARRAY_SIZE(sa11x0rtc_resources),
 };
 
 static struct platform_device *sa11x0_devices[] __initdata = {
diff --git a/arch/arm/mach-shmobile/include/mach/system.h b/arch/arm/mach-shmobile/include/mach/system.h
index 956ac18..3e9f823 100644
--- a/arch/arm/mach-shmobile/include/mach/system.h
+++ b/arch/arm/mach-shmobile/include/mach/system.h
@@ -6,6 +6,7 @@ static inline void arch_idle(void)
 	cpu_do_idle();
 }
 
+#error Fix me up
 static inline void arch_reset(char mode, const char *cmd)
 {
 	soft_restart(0);
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 1fa26d9..ea49bd9 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -19,6 +19,7 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/iomap.h>
 
@@ -58,6 +59,7 @@ unsigned long long tegra_chip_uid(void)
 	hi = fuse_readl(FUSE_UID_HIGH);
 	return (hi << 32ull) | lo;
 }
+EXPORT_SYMBOL(tegra_chip_uid);
 
 int tegra_sku_id(void)
 {
diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c
index 2b2d51c..0127490 100644
--- a/arch/arm/mach-ux500/mbox-db5500.c
+++ b/arch/arm/mach-ux500/mbox-db5500.c
@@ -168,7 +168,7 @@ static ssize_t mbox_read_fifo(struct device *dev,
 	return sprintf(buf, "0x%X\n", mbox_value);
 }
 
-static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
 
 static int mbox_show(struct seq_file *s, void *data)
 {
diff --git a/arch/arm/mach-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h
index d6c757e..787bcd2 100644
--- a/arch/arm/mach-vt8500/include/mach/system.h
+++ b/arch/arm/mach-vt8500/include/mach/system.h
@@ -12,6 +12,7 @@ static inline void arch_idle(void)
 	cpu_do_idle();
 }
 
+#error Fix me up
 static inline void arch_reset(char mode, const char *cmd)
 {
 	writel(1, VT8500_PMSR_VIRT);
diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c
index d2852e1..d130a5e 100644
--- a/arch/arm/mm/copypage-fa.c
+++ b/arch/arm/mm/copypage-fa.c
@@ -44,11 +44,11 @@ void fa_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	fa_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -58,7 +58,7 @@ void fa_copy_user_highpage(struct page *to, struct page *from,
  */
 void fa_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile("\
 	mov	r1, %2				@ 1\n\
 	mov	r2, #0				@ 1\n\
@@ -77,7 +77,7 @@ void fa_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 32)
 	: "r1", "r2", "r3", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns fa_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c
index ac163de..49ee0c1 100644
--- a/arch/arm/mm/copypage-feroceon.c
+++ b/arch/arm/mm/copypage-feroceon.c
@@ -72,17 +72,17 @@ void feroceon_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	flush_cache_page(vma, vaddr, page_to_pfn(from));
 	feroceon_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile ("\
 	mov	r1, %2				\n\
 	mov	r2, #0				\n\
@@ -102,7 +102,7 @@ void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 32)
 	: "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns feroceon_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c
index f72303e..3935bdd 100644
--- a/arch/arm/mm/copypage-v3.c
+++ b/arch/arm/mm/copypage-v3.c
@@ -42,11 +42,11 @@ void v3_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	v3_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -56,7 +56,7 @@ void v3_copy_user_highpage(struct page *to, struct page *from,
  */
 void v3_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile("\n\
 	mov	r1, %2				@ 1\n\
 	mov	r2, #0				@ 1\n\
@@ -72,7 +72,7 @@ void v3_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 64)
 	: "r1", "r2", "r3", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns v3_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
index 7d0a8c2..ec8c3be 100644
--- a/arch/arm/mm/copypage-v4mc.c
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -71,7 +71,7 @@ mc_copy_user_page(void *from, void *to)
 void v4_mc_copy_user_highpage(struct page *to, struct page *from,
 	unsigned long vaddr, struct vm_area_struct *vma)
 {
-	void *kto = kmap_atomic(to, KM_USER1);
+	void *kto = kmap_atomic(to);
 
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
@@ -85,7 +85,7 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
 
 	raw_spin_unlock(&minicache_lock);
 
-	kunmap_atomic(kto, KM_USER1);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -93,7 +93,7 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
  */
 void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile("\
 	mov	r1, %2				@ 1\n\
 	mov	r2, #0				@ 1\n\
@@ -111,7 +111,7 @@ void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 64)
 	: "r1", "r2", "r3", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns v4_mc_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c
index cb589cb..067d0fd 100644
--- a/arch/arm/mm/copypage-v4wb.c
+++ b/arch/arm/mm/copypage-v4wb.c
@@ -52,12 +52,12 @@ void v4wb_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	flush_cache_page(vma, vaddr, page_to_pfn(from));
 	v4wb_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -67,7 +67,7 @@ void v4wb_copy_user_highpage(struct page *to, struct page *from,
  */
 void v4wb_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile("\
 	mov	r1, %2				@ 1\n\
 	mov	r2, #0				@ 1\n\
@@ -86,7 +86,7 @@ void v4wb_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 64)
 	: "r1", "r2", "r3", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns v4wb_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-v4wt.c b/arch/arm/mm/copypage-v4wt.c
index 30c7d04..b85c5da 100644
--- a/arch/arm/mm/copypage-v4wt.c
+++ b/arch/arm/mm/copypage-v4wt.c
@@ -48,11 +48,11 @@ void v4wt_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	v4wt_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -62,7 +62,7 @@ void v4wt_copy_user_highpage(struct page *to, struct page *from,
  */
 void v4wt_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile("\
 	mov	r1, %2				@ 1\n\
 	mov	r2, #0				@ 1\n\
@@ -79,7 +79,7 @@ void v4wt_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 64)
 	: "r1", "r2", "r3", "ip", "lr");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns v4wt_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 3d9a155..8b03a58 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -38,11 +38,11 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
 {
 	void *kto, *kfrom;
 
-	kfrom = kmap_atomic(from, KM_USER0);
-	kto = kmap_atomic(to, KM_USER1);
+	kfrom = kmap_atomic(from);
+	kto = kmap_atomic(to);
 	copy_page(kto, kfrom);
-	kunmap_atomic(kto, KM_USER1);
-	kunmap_atomic(kfrom, KM_USER0);
+	kunmap_atomic(kto);
+	kunmap_atomic(kfrom);
 }
 
 /*
@@ -51,9 +51,9 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
  */
 static void v6_clear_user_highpage_nonaliasing(struct page *page, unsigned long vaddr)
 {
-	void *kaddr = kmap_atomic(page, KM_USER0);
+	void *kaddr = kmap_atomic(page);
 	clear_page(kaddr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 /*
diff --git a/arch/arm/mm/copypage-xsc3.c b/arch/arm/mm/copypage-xsc3.c
index f9cde07..03a2042 100644
--- a/arch/arm/mm/copypage-xsc3.c
+++ b/arch/arm/mm/copypage-xsc3.c
@@ -75,12 +75,12 @@ void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
 {
 	void *kto, *kfrom;
 
-	kto = kmap_atomic(to, KM_USER0);
-	kfrom = kmap_atomic(from, KM_USER1);
+	kto = kmap_atomic(to);
+	kfrom = kmap_atomic(from);
 	flush_cache_page(vma, vaddr, page_to_pfn(from));
 	xsc3_mc_copy_user_page(kto, kfrom);
-	kunmap_atomic(kfrom, KM_USER1);
-	kunmap_atomic(kto, KM_USER0);
+	kunmap_atomic(kfrom);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -90,7 +90,7 @@ void xsc3_mc_copy_user_highpage(struct page *to, struct page *from,
  */
 void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile ("\
 	mov	r1, %2				\n\
 	mov	r2, #0				\n\
@@ -105,7 +105,7 @@ void xsc3_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 32)
 	: "r1", "r2", "r3");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns xsc3_mc_user_fns __initdata = {
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
index 610c24c..439d106 100644
--- a/arch/arm/mm/copypage-xscale.c
+++ b/arch/arm/mm/copypage-xscale.c
@@ -93,7 +93,7 @@ mc_copy_user_page(void *from, void *to)
 void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 	unsigned long vaddr, struct vm_area_struct *vma)
 {
-	void *kto = kmap_atomic(to, KM_USER1);
+	void *kto = kmap_atomic(to);
 
 	if (!test_and_set_bit(PG_dcache_clean, &from->flags))
 		__flush_dcache_page(page_mapping(from), from);
@@ -107,7 +107,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 
 	raw_spin_unlock(&minicache_lock);
 
-	kunmap_atomic(kto, KM_USER1);
+	kunmap_atomic(kto);
 }
 
 /*
@@ -116,7 +116,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 void
 xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *ptr, *kaddr = kmap_atomic(page, KM_USER0);
+	void *ptr, *kaddr = kmap_atomic(page);
 	asm volatile(
 	"mov	r1, %2				\n\
 	mov	r2, #0				\n\
@@ -133,7 +133,7 @@ xscale_mc_clear_user_highpage(struct page *page, unsigned long vaddr)
 	: "=r" (ptr)
 	: "0" (kaddr), "I" (PAGE_SIZE / 32)
 	: "r1", "r2", "r3", "ip");
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 struct cpu_user_fns xscale_mc_user_fns __initdata = {
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index 807c057..5a21505 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -36,7 +36,7 @@ void kunmap(struct page *page)
 }
 EXPORT_SYMBOL(kunmap);
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	unsigned int idx;
 	unsigned long vaddr;
@@ -81,7 +81,7 @@ void *__kmap_atomic(struct page *page)
 
 	return (void *)vaddr;
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 6ec1226..5dc7d12 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -310,7 +310,7 @@ static void arm_memory_present(void)
 
 static bool arm_memblock_steal_permitted = true;
 
-phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
 {
 	phys_addr_t phys;
 
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index b30708e..dcebb12 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -17,26 +17,17 @@ config ARCH_IMX_V4_V5
 	  and ARMv5 SoCs
 
 config ARCH_IMX_V6_V7
-	bool "i.MX3, i.MX6"
+	bool "i.MX3, i.MX5, i.MX6"
 	select AUTO_ZRELADDR if !ZBOOT_ROM
 	select ARM_PATCH_PHYS_VIRT
 	select MIGHT_HAVE_CACHE_L2X0
 	help
-	  This enables support for systems based on the Freescale i.MX3 and i.MX6
-	  family.
-
-config ARCH_MX5
-	bool "i.MX50, i.MX51, i.MX53"
-	select AUTO_ZRELADDR if !ZBOOT_ROM
-	select ARM_PATCH_PHYS_VIRT
-	help
-	  This enables support for machines using Freescale's i.MX50 and i.MX53
-	  processors.
+	  This enables support for systems based on the Freescale i.MX3, i.MX5
+	  and i.MX6 family.
 
 endchoice
 
 source "arch/arm/mach-imx/Kconfig"
-source "arch/arm/mach-mx5/Kconfig"
 
 endmenu
 
diff --git a/arch/arm/plat-omap/include/plat/remoteproc.h b/arch/arm/plat-omap/include/plat/remoteproc.h
new file mode 100644
index 0000000..b10eac8
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/remoteproc.h
@@ -0,0 +1,57 @@
+/*
+ * Remote Processor - omap-specific bits
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 _PLAT_REMOTEPROC_H
+#define _PLAT_REMOTEPROC_H
+
+struct rproc_ops;
+struct platform_device;
+
+/*
+ * struct omap_rproc_pdata - omap remoteproc's platform data
+ * @name: the remoteproc's name
+ * @oh_name: omap hwmod device
+ * @oh_name_opt: optional, secondary omap hwmod device
+ * @firmware: name of firmware file to load
+ * @mbox_name: name of omap mailbox device to use with this rproc
+ * @ops: start/stop rproc handlers
+ * @device_enable: omap-specific handler for enabling a device
+ * @device_shutdown: omap-specific handler for shutting down a device
+ */
+struct omap_rproc_pdata {
+	const char *name;
+	const char *oh_name;
+	const char *oh_name_opt;
+	const char *firmware;
+	const char *mbox_name;
+	const struct rproc_ops *ops;
+	int (*device_enable) (struct platform_device *pdev);
+	int (*device_shutdown) (struct platform_device *pdev);
+};
+
+#if defined(CONFIG_OMAP_REMOTEPROC) || defined(CONFIG_OMAP_REMOTEPROC_MODULE)
+
+void __init omap_rproc_reserve_cma(void);
+
+#else
+
+void __init omap_rproc_reserve_cma(void)
+{
+}
+
+#endif
+
+#endif /* _PLAT_REMOTEPROC_H */
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 8167ce6..e7fec78 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -80,6 +80,11 @@ config S5P_DEV_FIMC3
 	help
 	  Compile in platform device definitions for FIMC controller 3
 
+config S5P_DEV_G2D
+	bool
+	help
+	  Compile in platform device definitions for G2D device
+
 config S5P_DEV_FIMD0
 	bool
 	help
diff --git a/arch/arm/plat-samsung/dev-backlight.c b/arch/arm/plat-samsung/dev-backlight.c
index a976c02..2254920 100644
--- a/arch/arm/plat-samsung/dev-backlight.c
+++ b/arch/arm/plat-samsung/dev-backlight.c
@@ -115,6 +115,8 @@ void samsung_bl_set(struct samsung_bl_gpio_info *gpio_info,
 		samsung_bl_data->init = bl_data->init;
 	if (bl_data->notify)
 		samsung_bl_data->notify = bl_data->notify;
+	if (bl_data->notify_after)
+		samsung_bl_data->notify_after = bl_data->notify_after;
 	if (bl_data->exit)
 		samsung_bl_data->exit = bl_data->exit;
 	if (bl_data->check_fb)
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index 32a6e39..145580a 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -267,6 +267,34 @@ struct platform_device s5p_device_fimc3 = {
 };
 #endif /* CONFIG_S5P_DEV_FIMC3 */
 
+/* G2D */
+
+#ifdef CONFIG_S5P_DEV_G2D
+static struct resource s5p_g2d_resource[] = {
+	[0] = {
+		.start	= S5P_PA_G2D,
+		.end	= S5P_PA_G2D + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_2D,
+		.end	= IRQ_2D,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device s5p_device_g2d = {
+	.name		= "s5p-g2d",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(s5p_g2d_resource),
+	.resource	= s5p_g2d_resource,
+	.dev		= {
+		.dma_mask		= &samsung_device_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+#endif /* CONFIG_S5P_DEV_G2D */
+
 /* FIMD0 */
 
 #ifdef CONFIG_S5P_DEV_FIMD0
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 4214ea0..bb45848 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -79,6 +79,7 @@ extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
 extern struct platform_device s5p_device_fimc3;
 extern struct platform_device s5p_device_fimc_md;
+extern struct platform_device s5p_device_g2d;
 extern struct platform_device s5p_device_fimd0;
 extern struct platform_device s5p_device_hdmi;
 extern struct platform_device s5p_device_i2c_hdmiphy;
diff --git a/arch/arm/plat-samsung/include/plat/dma-pl330.h b/arch/arm/plat-samsung/include/plat/dma-pl330.h
index c5eaad5..0670f37 100644
--- a/arch/arm/plat-samsung/include/plat/dma-pl330.h
+++ b/arch/arm/plat-samsung/include/plat/dma-pl330.h
@@ -82,6 +82,22 @@ enum dma_ch {
 	DMACH_SLIMBUS4_TX,
 	DMACH_SLIMBUS5_RX,
 	DMACH_SLIMBUS5_TX,
+	DMACH_MIPI_HSI0,
+	DMACH_MIPI_HSI1,
+	DMACH_MIPI_HSI2,
+	DMACH_MIPI_HSI3,
+	DMACH_MIPI_HSI4,
+	DMACH_MIPI_HSI5,
+	DMACH_MIPI_HSI6,
+	DMACH_MIPI_HSI7,
+	DMACH_MTOM_0,
+	DMACH_MTOM_1,
+	DMACH_MTOM_2,
+	DMACH_MTOM_3,
+	DMACH_MTOM_4,
+	DMACH_MTOM_5,
+	DMACH_MTOM_6,
+	DMACH_MTOM_7,
 	/* END Marker, also used to denote a reserved channel */
 	DMACH_MAX,
 };
diff --git a/arch/arm/plat-samsung/include/plat/regs-rtc.h b/arch/arm/plat-samsung/include/plat/regs-rtc.h
index 30b7cc1..0f8263e 100644
--- a/arch/arm/plat-samsung/include/plat/regs-rtc.h
+++ b/arch/arm/plat-samsung/include/plat/regs-rtc.h
@@ -18,51 +18,54 @@
 #define S3C2410_INTP_ALM	(1 << 1)
 #define S3C2410_INTP_TIC	(1 << 0)
 
-#define S3C2410_RTCCON	      S3C2410_RTCREG(0x40)
-#define S3C2410_RTCCON_RTCEN  (1<<0)
-#define S3C2410_RTCCON_CLKSEL (1<<1)
-#define S3C2410_RTCCON_CNTSEL (1<<2)
-#define S3C2410_RTCCON_CLKRST (1<<3)
-#define S3C64XX_RTCCON_TICEN  (1<<8)
+#define S3C2410_RTCCON		S3C2410_RTCREG(0x40)
+#define S3C2410_RTCCON_RTCEN	(1 << 0)
+#define S3C2410_RTCCON_CNTSEL	(1 << 2)
+#define S3C2410_RTCCON_CLKRST	(1 << 3)
+#define S3C2443_RTCCON_TICSEL	(1 << 4)
+#define S3C64XX_RTCCON_TICEN	(1 << 8)
 
-#define S3C64XX_RTCCON_TICMSK (0xF<<7)
-#define S3C64XX_RTCCON_TICSHT (7)
+#define S3C2410_TICNT		S3C2410_RTCREG(0x44)
+#define S3C2410_TICNT_ENABLE	(1 << 7)
 
-#define S3C2410_TICNT	      S3C2410_RTCREG(0x44)
-#define S3C2410_TICNT_ENABLE  (1<<7)
+/* S3C2443: tick count is 15 bit wide
+ * TICNT[6:0] contains upper 7 bits
+ * TICNT1[7:0] contains lower 8 bits
+ */
+#define S3C2443_TICNT_PART(x)	((x & 0x7f00) >> 8)
+#define S3C2443_TICNT1		S3C2410_RTCREG(0x4C)
+#define S3C2443_TICNT1_PART(x)	(x & 0xff)
 
-#define S3C2410_RTCALM	      S3C2410_RTCREG(0x50)
-#define S3C2410_RTCALM_ALMEN  (1<<6)
-#define S3C2410_RTCALM_YEAREN (1<<5)
-#define S3C2410_RTCALM_MONEN  (1<<4)
-#define S3C2410_RTCALM_DAYEN  (1<<3)
-#define S3C2410_RTCALM_HOUREN (1<<2)
-#define S3C2410_RTCALM_MINEN  (1<<1)
-#define S3C2410_RTCALM_SECEN  (1<<0)
+/* S3C2416: tick count is 32 bit wide
+ * TICNT[6:0] contains bits [14:8]
+ * TICNT1[7:0] contains lower 8 bits
+ * TICNT2[16:0] contains upper 17 bits
+ */
+#define S3C2416_TICNT2		S3C2410_RTCREG(0x48)
+#define S3C2416_TICNT2_PART(x)	((x & 0xffff8000) >> 15)
 
-#define S3C2410_RTCALM_ALL \
-  S3C2410_RTCALM_ALMEN | S3C2410_RTCALM_YEAREN | S3C2410_RTCALM_MONEN |\
-  S3C2410_RTCALM_DAYEN | S3C2410_RTCALM_HOUREN | S3C2410_RTCALM_MINEN |\
-  S3C2410_RTCALM_SECEN
+#define S3C2410_RTCALM		S3C2410_RTCREG(0x50)
+#define S3C2410_RTCALM_ALMEN	(1 << 6)
+#define S3C2410_RTCALM_YEAREN	(1 << 5)
+#define S3C2410_RTCALM_MONEN	(1 << 4)
+#define S3C2410_RTCALM_DAYEN	(1 << 3)
+#define S3C2410_RTCALM_HOUREN	(1 << 2)
+#define S3C2410_RTCALM_MINEN	(1 << 1)
+#define S3C2410_RTCALM_SECEN	(1 << 0)
 
+#define S3C2410_ALMSEC		S3C2410_RTCREG(0x54)
+#define S3C2410_ALMMIN		S3C2410_RTCREG(0x58)
+#define S3C2410_ALMHOUR		S3C2410_RTCREG(0x5c)
 
-#define S3C2410_ALMSEC	      S3C2410_RTCREG(0x54)
-#define S3C2410_ALMMIN	      S3C2410_RTCREG(0x58)
-#define S3C2410_ALMHOUR	      S3C2410_RTCREG(0x5c)
-
-#define S3C2410_ALMDATE	      S3C2410_RTCREG(0x60)
-#define S3C2410_ALMMON	      S3C2410_RTCREG(0x64)
-#define S3C2410_ALMYEAR	      S3C2410_RTCREG(0x68)
-
-#define S3C2410_RTCRST	      S3C2410_RTCREG(0x6c)
-
-#define S3C2410_RTCSEC	      S3C2410_RTCREG(0x70)
-#define S3C2410_RTCMIN	      S3C2410_RTCREG(0x74)
-#define S3C2410_RTCHOUR	      S3C2410_RTCREG(0x78)
-#define S3C2410_RTCDATE	      S3C2410_RTCREG(0x7c)
-#define S3C2410_RTCDAY	      S3C2410_RTCREG(0x80)
-#define S3C2410_RTCMON	      S3C2410_RTCREG(0x84)
-#define S3C2410_RTCYEAR	      S3C2410_RTCREG(0x88)
+#define S3C2410_ALMDATE		S3C2410_RTCREG(0x60)
+#define S3C2410_ALMMON		S3C2410_RTCREG(0x64)
+#define S3C2410_ALMYEAR		S3C2410_RTCREG(0x68)
 
+#define S3C2410_RTCSEC		S3C2410_RTCREG(0x70)
+#define S3C2410_RTCMIN		S3C2410_RTCREG(0x74)
+#define S3C2410_RTCHOUR		S3C2410_RTCREG(0x78)
+#define S3C2410_RTCDATE		S3C2410_RTCREG(0x7c)
+#define S3C2410_RTCMON		S3C2410_RTCREG(0x84)
+#define S3C2410_RTCYEAR		S3C2410_RTCREG(0x88)
 
 #endif /* __ASM_ARCH_REGS_RTC_H */
diff --git a/arch/arm/plat-samsung/include/plat/rtc-core.h b/arch/arm/plat-samsung/include/plat/rtc-core.h
new file mode 100644
index 0000000..21d8594
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/rtc-core.h
@@ -0,0 +1,27 @@
+/* linux/arch/arm/plat-samsung/include/plat/rtc-core.h
+ *
+ * Copyright (c) 2011 Heiko Stuebner <heiko@sntech.de>
+ *
+ * Samsung RTC Controller core functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_PLAT_RTC_CORE_H
+#define __ASM_PLAT_RTC_CORE_H __FILE__
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c_rtc_setname(char *name)
+{
+#if defined(CONFIG_SAMSUNG_DEV_RTC) || defined(CONFIG_PLAT_S3C24XX)
+	s3c_device_rtc.name = name;
+#endif
+}
+
+#endif /* __ASM_PLAT_RTC_CORE_H */
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index 642c6fe..f8476d9 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -1394,11 +1394,10 @@ static int create_md5_pad(int alloc_flag, unsigned long long hashed_length, char
 
 	if (padlen < MD5_MIN_PAD_LENGTH) padlen += MD5_BLOCK_LENGTH;
 
-	p = kmalloc(padlen, alloc_flag);
+	p = kzalloc(padlen, alloc_flag);
 	if (!p) return -ENOMEM;
 
 	*p = 0x80;
-	memset(p+1, 0, padlen - 1);
 
 	DEBUG(printk("create_md5_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
 
@@ -1426,11 +1425,10 @@ static int create_sha1_pad(int alloc_flag, unsigned long long hashed_length, cha
 
 	if (padlen < SHA1_MIN_PAD_LENGTH) padlen += SHA1_BLOCK_LENGTH;
 
-	p = kmalloc(padlen, alloc_flag);
+	p = kzalloc(padlen, alloc_flag);
 	if (!p) return -ENOMEM;
 
 	*p = 0x80;
-	memset(p+1, 0, padlen - 1);
 
 	DEBUG(printk("create_sha1_pad: hashed_length=%lld bits == %lld bytes\n", bit_length, hashed_length));
 
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c
index 511ece9..42ed6c7 100644
--- a/arch/cris/arch-v32/kernel/ptrace.c
+++ b/arch/cris/arch-v32/kernel/ptrace.c
@@ -115,8 +115,6 @@ void user_disable_single_step(struct task_struct *child)
 void
 ptrace_disable(struct task_struct *child)
 {
-	unsigned long tmp;
-
 	/* Deconfigure SPC and S-bit. */
 	user_disable_single_step(child);
 	put_reg(child, PT_SPC, 0);
diff --git a/arch/cris/include/arch-v32/arch/cache.h b/arch/cris/include/arch-v32/arch/cache.h
index 1de779f..7caf25d 100644
--- a/arch/cris/include/arch-v32/arch/cache.h
+++ b/arch/cris/include/arch-v32/arch/cache.h
@@ -7,7 +7,7 @@
 #define L1_CACHE_BYTES 32
 #define L1_CACHE_SHIFT 5
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 void flush_dma_list(dma_descr_data *descr);
 void flush_dma_descr(dma_descr_data *descr, int flush_buf);
diff --git a/arch/frv/include/asm/highmem.h b/arch/frv/include/asm/highmem.h
index a8d6565..716956a 100644
--- a/arch/frv/include/asm/highmem.h
+++ b/arch/frv/include/asm/highmem.h
@@ -157,7 +157,7 @@ static inline void kunmap_atomic_primary(void *kvaddr, enum km_type type)
 	pagefault_enable();
 }
 
-void *__kmap_atomic(struct page *page);
+void *kmap_atomic(struct page *page);
 void __kunmap_atomic(void *kvaddr);
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c
index fd7fcd4..31902c9 100644
--- a/arch/frv/mm/highmem.c
+++ b/arch/frv/mm/highmem.c
@@ -37,7 +37,7 @@ struct page *kmap_atomic_to_page(void *ptr)
 	return virt_to_page(ptr);
 }
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	unsigned long paddr;
 	int type;
@@ -64,7 +64,7 @@ void *__kmap_atomic(struct page *page)
 		return NULL;
 	}
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index 9059e39..acdc187 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -13,21 +13,19 @@ config HEXAGON
 	# select ARCH_REQUIRE_GPIOLIB
 	# select HAVE_CLK
 	# select IRQ_PER_CPU
-	select HAVE_IRQ_WORK
 	# select GENERIC_PENDING_IRQ if SMP
+	select HAVE_IRQ_WORK
 	select GENERIC_ATOMIC64
 	select HAVE_PERF_EVENTS
 	select HAVE_GENERIC_HARDIRQS
-	select GENERIC_HARDIRQS_NO__DO_IRQ
-	select GENERIC_HARDIRQS_NO_DEPRECATED
 	# GENERIC_ALLOCATOR is used by dma_alloc_coherent()
 	select GENERIC_ALLOCATOR
 	select GENERIC_IRQ_SHOW
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
 	select NO_IOPORT
+	select STACKTRACE_SUPPORT
 	select GENERIC_IOMAP
-	# mostly generic routines, with some accelerated ones
 	---help---
 	  Qualcomm Hexagon is a processor architecture designed for high
 	  performance and low power across a wide variety of applications.
@@ -74,15 +72,6 @@ config GENERIC_CSUM
 config GENERIC_IRQ_PROBE
 	def_bool y
 
-#config ZONE_DMA
-#	bool
-#	default y
-
-config HAS_DMA
-	bool
-	select HAVE_DMA_ATTRS
-	default y
-
 config NEED_SG_DMA_LENGTH
 	def_bool y
 
@@ -115,14 +104,11 @@ config GENERIC_BUG
 	def_bool y
 	depends on BUG
 
-config BUG
-	def_bool y
-
 menu "Machine selection"
 
 choice
 	prompt "System type"
-	default HEXAGON_ARCH_V2
+	default HEXAGON_COMET
 
 config HEXAGON_COMET
 	bool "Comet Board"
@@ -195,8 +181,7 @@ source "kernel/Kconfig.hz"
 source "kernel/time/Kconfig"
 
 config GENERIC_GPIO
-	bool "Generic GPIO support"
-	default n
+	def_bool n
 
 endmenu
 
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
index 0c4de87..9dfe1b9 100644
--- a/arch/hexagon/Makefile
+++ b/arch/hexagon/Makefile
@@ -52,7 +52,3 @@ core-y += arch/hexagon/kernel/ \
 	arch/hexagon/mm/ \
 	arch/hexagon/lib/
 
-#	arch/hexagon/platform/common/
-#
-#core-$(CONFIG_HEXAGON_COMET)		+= arch/hexagon/platform/comet/
-#machine-$(CONFIG_HEXAGON_COMET)		:= comet
diff --git a/arch/hexagon/include/asm/spinlock_types.h b/arch/hexagon/include/asm/spinlock_types.h
index 5e937af..99b5a75 100644
--- a/arch/hexagon/include/asm/spinlock_types.h
+++ b/arch/hexagon/include/asm/spinlock_types.h
@@ -21,8 +21,6 @@
 #ifndef _ASM_SPINLOCK_TYPES_H
 #define _ASM_SPINLOCK_TYPES_H
 
-#include <linux/version.h>
-
 #ifndef __LINUX_SPINLOCK_TYPES_H
 # error "please don't include this file directly"
 #endif
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index e711ace..54891e1 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -22,6 +22,7 @@
 #include <linux/bootmem.h>
 #include <linux/genalloc.h>
 #include <asm/dma-mapping.h>
+#include <linux/module.h>
 
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index bea3f08..8fe0349 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -28,6 +28,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/user.h>
+#include <linux/elf.h>
 
 #include <asm/system.h>
 #include <asm/user.h>
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
index 6bee15c..36ba641 100644
--- a/arch/hexagon/kernel/time.c
+++ b/arch/hexagon/kernel/time.c
@@ -28,6 +28,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/module.h>
 
 #include <asm/timer-regs.h>
 #include <asm/hexagon_vm.h>
@@ -200,12 +201,10 @@ void __init time_init_deferred(void)
 		resource = rtos_timer_device.resource;
 
 	/*  ioremap here means this has to run later, after paging init  */
-	rtos_timer = ioremap(resource->start, resource->end
-		- resource->start + 1);
+	rtos_timer = ioremap(resource->start, resource_size(resource));
 
 	if (!rtos_timer) {
-		release_mem_region(resource->start, resource->end
-			- resource->start + 1);
+		release_mem_region(resource->start, resource_size(resource));
 	}
 	clocksource_register_khz(&hexagon_clocksource, pcycle_freq_mhz * 1000);
 
diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c
index 16277c3..e4ceedb 100644
--- a/arch/hexagon/kernel/vdso.c
+++ b/arch/hexagon/kernel/vdso.c
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/binfmts.h>
 
 #include <asm/vdso.h>
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c4c1312..49470a6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2455,6 +2455,7 @@ config MIPS32_COMPAT
 config COMPAT
 	bool
 	depends on MIPS32_COMPAT
+	select ARCH_WANT_OLD_COMPAT_IPC
 	default y
 
 config SYSVIPC_COMPAT
diff --git a/arch/mips/alchemy/common/time.c b/arch/mips/alchemy/common/time.c
index 7da4d00..a7193ae 100644
--- a/arch/mips/alchemy/common/time.c
+++ b/arch/mips/alchemy/common/time.c
@@ -146,7 +146,7 @@ static int __init alchemy_time_init(unsigned int m2int)
 	cd->shift = 32;
 	cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift);
 	cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd);
-	cd->min_delta_ns = clockevent_delta2ns(8, cd);	/* ~0.25ms */
+	cd->min_delta_ns = clockevent_delta2ns(9, cd);	/* ~0.28ms */
 	clockevents_register_device(cd);
 	setup_irq(m2int, &au1x_rtcmatch2_irqaction);
 
diff --git a/arch/mips/configs/ase_defconfig b/arch/mips/configs/ase_defconfig
new file mode 100644
index 0000000..85ea780
--- /dev/null
+++ b/arch/mips/configs/ase_defconfig
@@ -0,0 +1,79 @@
+CONFIG_LANTIQ=y
+CONFIG_SOC_AMAZON_SE=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_DEFAULT_HOSTNAME="amazon_se"
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_ROOT_UID=1000
+CONFIG_INITRAMFS_ROOT_GID=1000
+# CONFIG_RD_GZIP is not set
+CONFIG_RD_LZMA=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+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
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_LANTIQ=y
+CONFIG_MISC_DEVICES=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_LANTIQ_ETOP=y
+CONFIG_PHYLIB=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_LANTIQ=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_LANTIQ_WDT=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
diff --git a/arch/mips/configs/falcon_defconfig b/arch/mips/configs/falcon_defconfig
new file mode 100644
index 0000000..8142a86
--- /dev/null
+++ b/arch/mips/configs/falcon_defconfig
@@ -0,0 +1,82 @@
+CONFIG_LANTIQ=y
+CONFIG_SOC_FALCON=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_DEFAULT_HOSTNAME="falcon"
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_ROOT_UID=1000
+CONFIG_INITRAMFS_ROOT_GID=1000
+CONFIG_RD_LZMA=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+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
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_LANTIQ=y
+CONFIG_MTD_M25P80=y
+CONFIG_MISC_DEVICES=y
+CONFIG_EEPROM_AT24=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_LANTIQ=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_FALCON=y
+CONFIG_SPI=y
+CONFIG_SPI_FALCON=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_WATCHDOG=y
+CONFIG_LANTIQ_WDT=y
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
diff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfig
new file mode 100644
index 0000000..704ec01
--- /dev/null
+++ b/arch/mips/configs/xway_defconfig
@@ -0,0 +1,80 @@
+CONFIG_LANTIQ=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_DEFAULT_HOSTNAME="danube"
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_ROOT_UID=1000
+CONFIG_INITRAMFS_ROOT_GID=1000
+# CONFIG_RD_GZIP is not set
+CONFIG_RD_LZMA=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_PCI=y
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+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
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_LANTIQ=y
+CONFIG_MISC_DEVICES=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_LANTIQ_ETOP=y
+CONFIG_PHYLIB=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_LANTIQ=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIO_SYSFS=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_LANTIQ_WDT=y
+# CONFIG_VGA_ARB is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h
index 77e6440..2d91888 100644
--- a/arch/mips/include/asm/highmem.h
+++ b/arch/mips/include/asm/highmem.h
@@ -47,7 +47,7 @@ extern void kunmap_high(struct page *page);
 
 extern void *kmap(struct page *page);
 extern void kunmap(struct page *page);
-extern void *__kmap_atomic(struct page *page);
+extern void *kmap_atomic(struct page *page);
 extern void __kunmap_atomic(void *kvaddr);
 extern void *kmap_atomic_pfn(unsigned long pfn);
 extern struct page *kmap_atomic_to_page(void *ptr);
diff --git a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
index 556e1be..fb9975c 100644
--- a/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
+++ b/arch/mips/include/asm/mach-au1x00/gpio-au1300.h
@@ -11,6 +11,9 @@
 #include <asm/io.h>
 #include <asm/mach-au1x00/au1000.h>
 
+struct gpio;
+struct gpio_chip;
+
 /* with the current GPIC design, up to 128 GPIOs are possible.
  * The only implementation so far is in the Au1300, which has 75 externally
  * available GPIOs.
@@ -203,7 +206,22 @@ static inline int gpio_request(unsigned int gpio, const char *label)
 	return 0;
 }
 
-static inline void gpio_free(unsigned int gpio)
+static inline int gpio_request_one(unsigned gpio,
+					unsigned long flags, const char *label)
+{
+	return 0;
+}
+
+static inline int gpio_request_array(struct gpio *array, size_t num)
+{
+	return 0;
+}
+
+static inline void gpio_free(unsigned gpio)
+{
+}
+
+static inline void gpio_free_array(struct gpio *array, size_t num)
 {
 }
 
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
new file mode 100644
index 0000000..4dc6466
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
@@ -0,0 +1,268 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ */
+
+#ifndef _FALCON_IRQ__
+#define _FALCON_IRQ__
+
+#define INT_NUM_IRQ0			8
+#define INT_NUM_IM0_IRL0		(INT_NUM_IRQ0 + 0)
+#define INT_NUM_IM1_IRL0		(INT_NUM_IM0_IRL0 + 32)
+#define INT_NUM_IM2_IRL0		(INT_NUM_IM1_IRL0 + 32)
+#define INT_NUM_IM3_IRL0		(INT_NUM_IM2_IRL0 + 32)
+#define INT_NUM_IM4_IRL0		(INT_NUM_IM3_IRL0 + 32)
+#define INT_NUM_EXTRA_START		(INT_NUM_IM4_IRL0 + 32)
+#define INT_NUM_IM_OFFSET		(INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
+
+#define MIPS_CPU_TIMER_IRQ			7
+
+/* HOST IF Event Interrupt */
+#define FALCON_IRQ_HOST				(INT_NUM_IM0_IRL0 + 0)
+/* HOST IF Mailbox0 Receive Interrupt */
+#define FALCON_IRQ_HOST_MB0_RX			(INT_NUM_IM0_IRL0 + 1)
+/* HOST IF Mailbox0 Transmit Interrupt */
+#define FALCON_IRQ_HOST_MB0_TX			(INT_NUM_IM0_IRL0 + 2)
+/* HOST IF Mailbox1 Receive Interrupt */
+#define FALCON_IRQ_HOST_MB1_RX			(INT_NUM_IM0_IRL0 + 3)
+/* HOST IF Mailbox1 Transmit Interrupt */
+#define FALCON_IRQ_HOST_MB1_TX			(INT_NUM_IM0_IRL0 + 4)
+/* I2C Last Single Data Transfer Request */
+#define FALCON_IRQ_I2C_LSREQ			(INT_NUM_IM0_IRL0 + 8)
+/* I2C Single Data Transfer Request */
+#define FALCON_IRQ_I2C_SREQ			(INT_NUM_IM0_IRL0 + 9)
+/* I2C Last Burst Data Transfer Request */
+#define FALCON_IRQ_I2C_LBREQ			(INT_NUM_IM0_IRL0 + 10)
+/* I2C Burst Data Transfer Request */
+#define FALCON_IRQ_I2C_BREQ			(INT_NUM_IM0_IRL0 + 11)
+/* I2C Error Interrupt */
+#define FALCON_IRQ_I2C_I2C_ERR			(INT_NUM_IM0_IRL0 + 12)
+/* I2C Protocol Interrupt */
+#define FALCON_IRQ_I2C_I2C_P			(INT_NUM_IM0_IRL0 + 13)
+/* SSC Transmit Interrupt */
+#define FALCON_IRQ_SSC_T			(INT_NUM_IM0_IRL0 + 14)
+/* SSC Receive Interrupt */
+#define FALCON_IRQ_SSC_R			(INT_NUM_IM0_IRL0 + 15)
+/* SSC Error Interrupt */
+#define FALCON_IRQ_SSC_E			(INT_NUM_IM0_IRL0 + 16)
+/* SSC Frame Interrupt */
+#define FALCON_IRQ_SSC_F			(INT_NUM_IM0_IRL0 + 17)
+/* Advanced Encryption Standard Interrupt */
+#define FALCON_IRQ_AES_AES			(INT_NUM_IM0_IRL0 + 27)
+/* Secure Hash Algorithm Interrupt */
+#define FALCON_IRQ_SHA_HASH			(INT_NUM_IM0_IRL0 + 28)
+/* PCM Receive Interrupt */
+#define FALCON_IRQ_PCM_RX			(INT_NUM_IM0_IRL0 + 29)
+/* PCM Transmit Interrupt */
+#define FALCON_IRQ_PCM_TX			(INT_NUM_IM0_IRL0 + 30)
+/* PCM Transmit Crash Interrupt */
+#define FALCON_IRQ_PCM_HW2_CRASH		(INT_NUM_IM0_IRL0 + 31)
+
+/* EBU Serial Flash Command Error */
+#define FALCON_IRQ_EBU_SF_CMDERR		(INT_NUM_IM1_IRL0 + 0)
+/* EBU Serial Flash Command Overwrite Error */
+#define FALCON_IRQ_EBU_SF_COVERR		(INT_NUM_IM1_IRL0 + 1)
+/* EBU Serial Flash Busy */
+#define FALCON_IRQ_EBU_SF_BUSY			(INT_NUM_IM1_IRL0 + 2)
+/* External Interrupt from GPIO P0 */
+#define FALCON_IRQ_GPIO_P0			(INT_NUM_IM1_IRL0 + 4)
+/* External Interrupt from GPIO P1 */
+#define FALCON_IRQ_GPIO_P1			(INT_NUM_IM1_IRL0 + 5)
+/* External Interrupt from GPIO P2 */
+#define FALCON_IRQ_GPIO_P2			(INT_NUM_IM1_IRL0 + 6)
+/* External Interrupt from GPIO P3 */
+#define FALCON_IRQ_GPIO_P3			(INT_NUM_IM1_IRL0 + 7)
+/* External Interrupt from GPIO P4 */
+#define FALCON_IRQ_GPIO_P4			(INT_NUM_IM1_IRL0 + 8)
+/* 8kHz backup interrupt derived from core-PLL */
+#define FALCON_IRQ_FSC_BKP			(INT_NUM_IM1_IRL0 + 10)
+/* FSC Timer Interrupt 0 */
+#define FALCON_IRQ_FSCT_CMP0			(INT_NUM_IM1_IRL0 + 11)
+/* FSC Timer Interrupt 1 */
+#define FALCON_IRQ_FSCT_CMP1			(INT_NUM_IM1_IRL0 + 12)
+/* 8kHz root interrupt derived from GPON interface */
+#define FALCON_IRQ_FSC_ROOT			(INT_NUM_IM1_IRL0 + 13)
+/* Time of Day */
+#define FALCON_IRQ_TOD				(INT_NUM_IM1_IRL0 + 14)
+/* PMA Interrupt from IntNode of the 200MHz Domain */
+#define FALCON_IRQ_PMA_200M			(INT_NUM_IM1_IRL0 + 15)
+/* PMA Interrupt from IntNode of the TX Clk Domain */
+#define FALCON_IRQ_PMA_TX			(INT_NUM_IM1_IRL0 + 16)
+/* PMA Interrupt from IntNode of the RX Clk Domain */
+#define FALCON_IRQ_PMA_RX			(INT_NUM_IM1_IRL0 + 17)
+/* SYS1 Interrupt */
+#define FALCON_IRQ_SYS1				(INT_NUM_IM1_IRL0 + 20)
+/* SYS GPE Interrupt */
+#define FALCON_IRQ_SYS_GPE			(INT_NUM_IM1_IRL0 + 21)
+/* Watchdog Access Error Interrupt */
+#define FALCON_IRQ_WDT_AEIR			(INT_NUM_IM1_IRL0 + 24)
+/* Watchdog Prewarning Interrupt */
+#define FALCON_IRQ_WDT_PIR			(INT_NUM_IM1_IRL0 + 25)
+/* SBIU interrupt */
+#define FALCON_IRQ_SBIU0			(INT_NUM_IM1_IRL0 + 27)
+/* FPI Bus Control Unit Interrupt */
+#define FALCON_IRQ_BCU0				(INT_NUM_IM1_IRL0 + 29)
+/* DDR Controller Interrupt */
+#define FALCON_IRQ_DDR				(INT_NUM_IM1_IRL0 + 30)
+/* Crossbar Error Interrupt */
+#define FALCON_IRQ_XBAR_ERROR			(INT_NUM_IM1_IRL0 + 31)
+
+/* ICTRLL 0 Interrupt */
+#define FALCON_IRQ_ICTRLL0			(INT_NUM_IM2_IRL0 + 0)
+/* ICTRLL 1 Interrupt */
+#define FALCON_IRQ_ICTRLL1			(INT_NUM_IM2_IRL0 + 1)
+/* ICTRLL 2 Interrupt */
+#define FALCON_IRQ_ICTRLL2			(INT_NUM_IM2_IRL0 + 2)
+/* ICTRLL 3 Interrupt */
+#define FALCON_IRQ_ICTRLL3			(INT_NUM_IM2_IRL0 + 3)
+/* OCTRLL 0 Interrupt */
+#define FALCON_IRQ_OCTRLL0			(INT_NUM_IM2_IRL0 + 4)
+/* OCTRLL 1 Interrupt */
+#define FALCON_IRQ_OCTRLL1			(INT_NUM_IM2_IRL0 + 5)
+/* OCTRLL 2 Interrupt */
+#define FALCON_IRQ_OCTRLL2			(INT_NUM_IM2_IRL0 + 6)
+/* OCTRLL 3 Interrupt */
+#define FALCON_IRQ_OCTRLL3			(INT_NUM_IM2_IRL0 + 7)
+/* OCTRLG Interrupt */
+#define FALCON_IRQ_OCTRLG			(INT_NUM_IM2_IRL0 + 9)
+/* IQM Interrupt */
+#define FALCON_IRQ_IQM				(INT_NUM_IM2_IRL0 + 10)
+/* FSQM Interrupt */
+#define FALCON_IRQ_FSQM				(INT_NUM_IM2_IRL0 + 11)
+/* TMU Interrupt */
+#define FALCON_IRQ_TMU				(INT_NUM_IM2_IRL0 + 12)
+/* LINK1 Interrupt */
+#define FALCON_IRQ_LINK1			(INT_NUM_IM2_IRL0 + 14)
+/* ICTRLC 0 Interrupt */
+#define FALCON_IRQ_ICTRLC0			(INT_NUM_IM2_IRL0 + 16)
+/* ICTRLC 1 Interrupt */
+#define FALCON_IRQ_ICTRLC1			(INT_NUM_IM2_IRL0 + 17)
+/* OCTRLC Interrupt */
+#define FALCON_IRQ_OCTRLC			(INT_NUM_IM2_IRL0 + 18)
+/* CONFIG Break Interrupt */
+#define FALCON_IRQ_CONFIG_BREAK			(INT_NUM_IM2_IRL0 + 19)
+/* CONFIG Interrupt */
+#define FALCON_IRQ_CONFIG			(INT_NUM_IM2_IRL0 + 20)
+/* Dispatcher Interrupt */
+#define FALCON_IRQ_DISP				(INT_NUM_IM2_IRL0 + 21)
+/* TBM Interrupt */
+#define FALCON_IRQ_TBM				(INT_NUM_IM2_IRL0 + 22)
+/* GTC Downstream Interrupt */
+#define FALCON_IRQ_GTC_DS			(INT_NUM_IM2_IRL0 + 29)
+/* GTC Upstream Interrupt */
+#define FALCON_IRQ_GTC_US			(INT_NUM_IM2_IRL0 + 30)
+/* EIM Interrupt */
+#define FALCON_IRQ_EIM				(INT_NUM_IM2_IRL0 + 31)
+
+/* ASC0 Transmit Interrupt */
+#define FALCON_IRQ_ASC0_T			(INT_NUM_IM3_IRL0 + 0)
+/* ASC0 Receive Interrupt */
+#define FALCON_IRQ_ASC0_R			(INT_NUM_IM3_IRL0 + 1)
+/* ASC0 Error Interrupt */
+#define FALCON_IRQ_ASC0_E			(INT_NUM_IM3_IRL0 + 2)
+/* ASC0 Transmit Buffer Interrupt */
+#define FALCON_IRQ_ASC0_TB			(INT_NUM_IM3_IRL0 + 3)
+/* ASC0 Autobaud Start Interrupt */
+#define FALCON_IRQ_ASC0_ABST			(INT_NUM_IM3_IRL0 + 4)
+/* ASC0 Autobaud Detection Interrupt */
+#define FALCON_IRQ_ASC0_ABDET			(INT_NUM_IM3_IRL0 + 5)
+/* ASC1 Modem Status Interrupt */
+#define FALCON_IRQ_ASC0_MS			(INT_NUM_IM3_IRL0 + 6)
+/* ASC0 Soft Flow Control Interrupt */
+#define FALCON_IRQ_ASC0_SFC			(INT_NUM_IM3_IRL0 + 7)
+/* ASC1 Transmit Interrupt */
+#define FALCON_IRQ_ASC1_T			(INT_NUM_IM3_IRL0 + 8)
+/* ASC1 Receive Interrupt */
+#define FALCON_IRQ_ASC1_R			(INT_NUM_IM3_IRL0 + 9)
+/* ASC1 Error Interrupt */
+#define FALCON_IRQ_ASC1_E			(INT_NUM_IM3_IRL0 + 10)
+/* ASC1 Transmit Buffer Interrupt */
+#define FALCON_IRQ_ASC1_TB			(INT_NUM_IM3_IRL0 + 11)
+/* ASC1 Autobaud Start Interrupt */
+#define FALCON_IRQ_ASC1_ABST			(INT_NUM_IM3_IRL0 + 12)
+/* ASC1 Autobaud Detection Interrupt */
+#define FALCON_IRQ_ASC1_ABDET			(INT_NUM_IM3_IRL0 + 13)
+/* ASC1 Modem Status Interrupt */
+#define FALCON_IRQ_ASC1_MS			(INT_NUM_IM3_IRL0 + 14)
+/* ASC1 Soft Flow Control Interrupt */
+#define FALCON_IRQ_ASC1_SFC			(INT_NUM_IM3_IRL0 + 15)
+/* GPTC Timer/Counter 1A Interrupt */
+#define FALCON_IRQ_GPTC_TC1A			(INT_NUM_IM3_IRL0 + 16)
+/* GPTC Timer/Counter 1B Interrupt */
+#define FALCON_IRQ_GPTC_TC1B			(INT_NUM_IM3_IRL0 + 17)
+/* GPTC Timer/Counter 2A Interrupt */
+#define FALCON_IRQ_GPTC_TC2A			(INT_NUM_IM3_IRL0 + 18)
+/* GPTC Timer/Counter 2B Interrupt */
+#define FALCON_IRQ_GPTC_TC2B			(INT_NUM_IM3_IRL0 + 19)
+/* GPTC Timer/Counter 3A Interrupt */
+#define FALCON_IRQ_GPTC_TC3A			(INT_NUM_IM3_IRL0 + 20)
+/* GPTC Timer/Counter 3B Interrupt */
+#define FALCON_IRQ_GPTC_TC3B			(INT_NUM_IM3_IRL0 + 21)
+/* DFEV0, Channel 1 Transmit Interrupt */
+#define FALCON_IRQ_DFEV0_2TX			(INT_NUM_IM3_IRL0 + 26)
+/* DFEV0, Channel 1 Receive Interrupt */
+#define FALCON_IRQ_DFEV0_2RX			(INT_NUM_IM3_IRL0 + 27)
+/* DFEV0, Channel 1 General Purpose Interrupt */
+#define FALCON_IRQ_DFEV0_2GP			(INT_NUM_IM3_IRL0 + 28)
+/* DFEV0, Channel 0 Transmit Interrupt */
+#define FALCON_IRQ_DFEV0_1TX			(INT_NUM_IM3_IRL0 + 29)
+/* DFEV0, Channel 0 Receive Interrupt */
+#define FALCON_IRQ_DFEV0_1RX			(INT_NUM_IM3_IRL0 + 30)
+/* DFEV0, Channel 0 General Purpose Interrupt */
+#define FALCON_IRQ_DFEV0_1GP			(INT_NUM_IM3_IRL0 + 31)
+
+/* ICTRLL 0 Error */
+#define FALCON_IRQ_ICTRLL0_ERR			(INT_NUM_IM4_IRL0 + 0)
+/* ICTRLL 1 Error */
+#define FALCON_IRQ_ICTRLL1_ERR			(INT_NUM_IM4_IRL0 + 1)
+/* ICTRLL 2 Error */
+#define FALCON_IRQ_ICTRLL2_ERR			(INT_NUM_IM4_IRL0 + 2)
+/* ICTRLL 3 Error */
+#define FALCON_IRQ_ICTRLL3_ERR			(INT_NUM_IM4_IRL0 + 3)
+/* OCTRLL 0 Error */
+#define FALCON_IRQ_OCTRLL0_ERR			(INT_NUM_IM4_IRL0 + 4)
+/* OCTRLL 1 Error */
+#define FALCON_IRQ_OCTRLL1_ERR			(INT_NUM_IM4_IRL0 + 5)
+/* OCTRLL 2 Error */
+#define FALCON_IRQ_OCTRLL2_ERR			(INT_NUM_IM4_IRL0 + 6)
+/* OCTRLL 3 Error */
+#define FALCON_IRQ_OCTRLL3_ERR			(INT_NUM_IM4_IRL0 + 7)
+/* ICTRLG Error */
+#define FALCON_IRQ_ICTRLG_ERR			(INT_NUM_IM4_IRL0 + 8)
+/* OCTRLG Error */
+#define FALCON_IRQ_OCTRLG_ERR			(INT_NUM_IM4_IRL0 + 9)
+/* IQM Error */
+#define FALCON_IRQ_IQM_ERR			(INT_NUM_IM4_IRL0 + 10)
+/* FSQM Error */
+#define FALCON_IRQ_FSQM_ERR			(INT_NUM_IM4_IRL0 + 11)
+/* TMU Error */
+#define FALCON_IRQ_TMU_ERR			(INT_NUM_IM4_IRL0 + 12)
+/* MPS Status Interrupt #0 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR0			(INT_NUM_IM4_IRL0 + 14)
+/* MPS Status Interrupt #1 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR1			(INT_NUM_IM4_IRL0 + 15)
+/* MPS Status Interrupt #2 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR2			(INT_NUM_IM4_IRL0 + 16)
+/* MPS Status Interrupt #3 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR3			(INT_NUM_IM4_IRL0 + 17)
+/* MPS Status Interrupt #4 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR4			(INT_NUM_IM4_IRL0 + 18)
+/* MPS Status Interrupt #5 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR5			(INT_NUM_IM4_IRL0 + 19)
+/* MPS Status Interrupt #6 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR6			(INT_NUM_IM4_IRL0 + 20)
+/* MPS Status Interrupt #7 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR7			(INT_NUM_IM4_IRL0 + 21)
+/* MPS Status Interrupt #8 (VPE1 to VPE0) */
+#define FALCON_IRQ_MPS_IR8			(INT_NUM_IM4_IRL0 + 22)
+/* VPE0 Exception Level Flag Interrupt */
+#define FALCON_IRQ_VPE0_EXL			(INT_NUM_IM4_IRL0 + 29)
+/* VPE0 Error Level Flag Interrupt */
+#define FALCON_IRQ_VPE0_ERL			(INT_NUM_IM4_IRL0 + 30)
+/* VPE0 Performance Monitoring Counter Interrupt */
+#define FALCON_IRQ_VPE0_PMCIR			(INT_NUM_IM4_IRL0 + 31)
+
+#endif /* _FALCON_IRQ__ */
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/irq.h b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
new file mode 100644
index 0000000..2caccd9
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
@@ -0,0 +1,18 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ */
+
+#ifndef __FALCON_IRQ_H
+#define __FALCON_IRQ_H
+
+#include <falcon_irq.h>
+
+#define NR_IRQS 328
+
+#include_next <irq.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
new file mode 100644
index 0000000..8ac509a
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_FALCON_H__
+#define _LTQ_FALCON_H__
+
+#ifdef CONFIG_SOC_FALCON
+
+#include <lantiq.h>
+
+/* Chip IDs */
+#define SOC_ID_FALCON		0x01B8
+
+/* SoC Types */
+#define SOC_TYPE_FALCON		0x01
+
+/* ASC0/1 - serial port */
+#define LTQ_ASC0_BASE_ADDR	0x1E100C00
+#define LTQ_ASC1_BASE_ADDR	0x1E100B00
+#define LTQ_ASC_SIZE		0x100
+
+#define LTQ_ASC_TIR(x)          (INT_NUM_IM3_IRL0 + (x * 8))
+#define LTQ_ASC_RIR(x)          (INT_NUM_IM3_IRL0 + (x * 8) + 1)
+#define LTQ_ASC_EIR(x)          (INT_NUM_IM3_IRL0 + (x * 8) + 2)
+
+/*
+ * during early_printk no ioremap possible at this early stage
+ * lets use KSEG1 instead
+ */
+#define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
+
+/* ICU - interrupt control unit */
+#define LTQ_ICU_BASE_ADDR	0x1F880200
+#define LTQ_ICU_SIZE		0x100
+
+/* WDT */
+#define LTQ_WDT_BASE_ADDR	0x1F8803F0
+#define LTQ_WDT_SIZE		0x10
+
+#define LTQ_RST_CAUSE_WDTRST	0x0002
+
+/* EBU - external bus unit */
+#define LTQ_EBU_BASE_ADDR       0x18000000
+#define LTQ_EBU_SIZE            0x0100
+
+#define LTQ_EBU_MODCON  0x000C
+
+/* GPIO */
+#define LTQ_GPIO0_BASE_ADDR     0x1D810000
+#define LTQ_GPIO0_SIZE          0x0080
+#define LTQ_GPIO1_BASE_ADDR     0x1E800100
+#define LTQ_GPIO1_SIZE          0x0080
+#define LTQ_GPIO2_BASE_ADDR     0x1D810100
+#define LTQ_GPIO2_SIZE          0x0080
+#define LTQ_GPIO3_BASE_ADDR     0x1E800200
+#define LTQ_GPIO3_SIZE          0x0080
+#define LTQ_GPIO4_BASE_ADDR     0x1E800300
+#define LTQ_GPIO4_SIZE          0x0080
+#define LTQ_PADCTRL0_BASE_ADDR  0x1DB01000
+#define LTQ_PADCTRL0_SIZE       0x0100
+#define LTQ_PADCTRL1_BASE_ADDR  0x1E800400
+#define LTQ_PADCTRL1_SIZE       0x0100
+#define LTQ_PADCTRL2_BASE_ADDR  0x1DB02000
+#define LTQ_PADCTRL2_SIZE       0x0100
+#define LTQ_PADCTRL3_BASE_ADDR  0x1E800500
+#define LTQ_PADCTRL3_SIZE       0x0100
+#define LTQ_PADCTRL4_BASE_ADDR  0x1E800600
+#define LTQ_PADCTRL4_SIZE       0x0100
+
+/* CHIP ID */
+#define LTQ_STATUS_BASE_ADDR	0x1E802000
+
+#define LTQ_FALCON_CHIPID	((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x0c))
+#define LTQ_FALCON_CHIPTYPE	((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x38))
+#define LTQ_FALCON_CHIPCONF	((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x40))
+
+/* SYSCTL - start/stop/restart/configure/... different parts of the Soc */
+#define LTQ_SYS1_BASE_ADDR      0x1EF00000
+#define LTQ_SYS1_SIZE           0x0100
+#define LTQ_STATUS_BASE_ADDR	0x1E802000
+#define LTQ_STATUS_SIZE		0x0080
+#define LTQ_SYS_ETH_BASE_ADDR	0x1DB00000
+#define LTQ_SYS_ETH_SIZE	0x0100
+#define LTQ_SYS_GPE_BASE_ADDR	0x1D700000
+#define LTQ_SYS_GPE_SIZE	0x0100
+
+#define SYSCTL_SYS1		0
+#define SYSCTL_SYSETH		1
+#define SYSCTL_SYSGPE		2
+
+/* Activation Status Register */
+#define ACTS_ASC1_ACT	0x00000800
+#define ACTS_P0		0x00010000
+#define ACTS_P1		0x00010000
+#define ACTS_P2		0x00020000
+#define ACTS_P3		0x00020000
+#define ACTS_P4		0x00040000
+#define ACTS_PADCTRL0	0x00100000
+#define ACTS_PADCTRL1	0x00100000
+#define ACTS_PADCTRL2	0x00200000
+#define ACTS_PADCTRL3	0x00200000
+#define ACTS_PADCTRL4	0x00400000
+
+extern void ltq_sysctl_activate(int module, unsigned int mask);
+extern void ltq_sysctl_deactivate(int module, unsigned int mask);
+extern void ltq_sysctl_clken(int module, unsigned int mask);
+extern void ltq_sysctl_clkdis(int module, unsigned int mask);
+extern void ltq_sysctl_reboot(int module, unsigned int mask);
+extern int ltq_gpe_is_activated(unsigned int mask);
+
+/* global register ranges */
+extern void __iomem *ltq_ebu_membase;
+extern void __iomem *ltq_sys1_membase;
+static inline void ltq_ebu_w32(u32 v, u32 r)
+{
+	ltq_w32(v, ltq_ebu_membase + r);
+}
+static inline u32 ltq_ebu_r32(u32 r)
+{
+	return ltq_r32(ltq_ebu_membase + r);
+}
+static inline void ltq_ebu_w32_mask(u32 c, u32 s, u32 r)
+{
+	ltq_ebu_w32((ltq_ebu_r32(r) & ~(c)) | (s), r);
+}
+static inline void ltq_sys1_w32(u32 v, u32 r)
+{
+	ltq_w32(v, ltq_sys1_membase + r);
+}
+static inline u32 ltq_sys1_r32(u32 r)
+{
+	return ltq_r32(ltq_sys1_membase + r);
+}
+static inline void ltq_sys1_w32_mask(u32 c, u32 s, u32 r)
+{
+	ltq_sys1_w32((ltq_sys1_r32(r) & ~(c)) | (s), r);
+}
+
+/* gpio_request wrapper to help configure the pin */
+extern int  ltq_gpio_request(unsigned int pin, unsigned int mux,
+				unsigned int dir, const char *name);
+extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux);
+
+/* to keep the irq code generic we need to define these to 0 as falcon
+   has no EIU/EBU */
+#define LTQ_EIU_BASE_ADDR	0
+#define LTQ_EBU_PCC_ISTAT	0
+
+#define ltq_is_ar9()	0
+#define ltq_is_vr9()	0
+
+#endif /* CONFIG_SOC_FALCON */
+#endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index ce2f029..bf05854 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -9,23 +9,17 @@
 #define _LANTIQ_H__
 
 #include <linux/irq.h>
+#include <linux/ioport.h>
 
-/* generic reg access functions */
+/* generic reg access */
 #define ltq_r32(reg)		__raw_readl(reg)
 #define ltq_w32(val, reg)	__raw_writel(val, reg)
-#define ltq_w32_mask(clear, set, reg)	\
-	ltq_w32((ltq_r32(reg) & ~(clear)) | (set), reg)
 #define ltq_r8(reg)		__raw_readb(reg)
 #define ltq_w8(val, reg)	__raw_writeb(val, reg)
-
-/* register access macros for EBU and CGU */
-#define ltq_ebu_w32(x, y)	ltq_w32((x), ltq_ebu_membase + (y))
-#define ltq_ebu_r32(x)		ltq_r32(ltq_ebu_membase + (x))
-#define ltq_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
-#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
-
-extern __iomem void *ltq_ebu_membase;
-extern __iomem void *ltq_cgu_membase;
+static inline void ltq_w32_mask(u32 c, u32 s, volatile void __iomem *r)
+{
+	ltq_w32((ltq_r32(r) & ~(c)) | (s), r);
+}
 
 extern unsigned int ltq_get_cpu_ver(void);
 extern unsigned int ltq_get_soc_type(void);
@@ -33,6 +27,7 @@ extern unsigned int ltq_get_soc_type(void);
 /* clock speeds */
 #define CLOCK_60M	60000000
 #define CLOCK_83M	83333333
+#define CLOCK_100M	100000000
 #define CLOCK_111M	111111111
 #define CLOCK_133M	133333333
 #define CLOCK_167M	166666667
@@ -51,7 +46,9 @@ extern void ltq_enable_irq(struct irq_data *data);
 
 /* find out what caused the last cpu reset */
 extern int ltq_reset_cause(void);
-#define LTQ_RST_CAUSE_WDTRST	0x20
+
+/* helper for requesting and remapping resources */
+extern void __iomem *ltq_remap_resource(struct resource *res);
 
 #define IOPORT_RESOURCE_START	0x10000000
 #define IOPORT_RESOURCE_END	0xffffffff
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
index b4465a8..2a8d5ad 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -38,26 +38,8 @@
 
 #define MIPS_CPU_TIMER_IRQ		7
 
-#define LTQ_DMA_CH0_INT		(INT_NUM_IM2_IRL0)
-#define LTQ_DMA_CH1_INT		(INT_NUM_IM2_IRL0 + 1)
-#define LTQ_DMA_CH2_INT		(INT_NUM_IM2_IRL0 + 2)
-#define LTQ_DMA_CH3_INT		(INT_NUM_IM2_IRL0 + 3)
-#define LTQ_DMA_CH4_INT		(INT_NUM_IM2_IRL0 + 4)
-#define LTQ_DMA_CH5_INT		(INT_NUM_IM2_IRL0 + 5)
-#define LTQ_DMA_CH6_INT		(INT_NUM_IM2_IRL0 + 6)
-#define LTQ_DMA_CH7_INT		(INT_NUM_IM2_IRL0 + 7)
-#define LTQ_DMA_CH8_INT		(INT_NUM_IM2_IRL0 + 8)
-#define LTQ_DMA_CH9_INT		(INT_NUM_IM2_IRL0 + 9)
-#define LTQ_DMA_CH10_INT	(INT_NUM_IM2_IRL0 + 10)
-#define LTQ_DMA_CH11_INT	(INT_NUM_IM2_IRL0 + 11)
-#define LTQ_DMA_CH12_INT	(INT_NUM_IM2_IRL0 + 25)
-#define LTQ_DMA_CH13_INT	(INT_NUM_IM2_IRL0 + 26)
-#define LTQ_DMA_CH14_INT	(INT_NUM_IM2_IRL0 + 27)
-#define LTQ_DMA_CH15_INT	(INT_NUM_IM2_IRL0 + 28)
-#define LTQ_DMA_CH16_INT	(INT_NUM_IM2_IRL0 + 29)
-#define LTQ_DMA_CH17_INT	(INT_NUM_IM2_IRL0 + 30)
-#define LTQ_DMA_CH18_INT	(INT_NUM_IM2_IRL0 + 16)
-#define LTQ_DMA_CH19_INT	(INT_NUM_IM2_IRL0 + 21)
+#define LTQ_DMA_ETOP		((ltq_is_ase()) ? \
+				(INT_NUM_IM3_IRL0) : (INT_NUM_IM2_IRL0))
 
 #define LTQ_PPE_MBOX_INT	(INT_NUM_IM2_IRL0 + 24)
 
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 8a3c6be..9d0afeb 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -34,6 +34,12 @@
 #define LTQ_ASC1_BASE_ADDR	0x1E100C00
 #define LTQ_ASC_SIZE		0x400
 
+/*
+ * during early_printk no ioremap is possible
+ * lets use KSEG1 instead
+ */
+#define LTQ_EARLY_ASC		KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
+
 /* RCU - reset control unit */
 #define LTQ_RCU_BASE_ADDR	0x1F203000
 #define LTQ_RCU_SIZE		0x1000
@@ -61,6 +67,8 @@
 #define LTQ_CGU_BASE_ADDR	0x1F103000
 #define LTQ_CGU_SIZE		0x1000
 
+#define CGU_EPHY		0x10
+
 /* ICU - interrupt control unit */
 #define LTQ_ICU_BASE_ADDR	0x1F880200
 #define LTQ_ICU_SIZE		0x100
@@ -74,6 +82,7 @@
 #define LTQ_PMU_SIZE		0x1000
 
 #define PMU_DMA			0x0020
+#define PMU_EPHY		0x0080
 #define PMU_USB			0x8041
 #define PMU_LED			0x0800
 #define PMU_GPT			0x1000
@@ -85,6 +94,10 @@
 #define LTQ_ETOP_BASE_ADDR	0x1E180000
 #define LTQ_ETOP_SIZE		0x40000
 
+/* GBIT - gigabit switch */
+#define LTQ_GBIT_BASE_ADDR	0x1E108000
+#define LTQ_GBIT_SIZE		0x200
+
 /* DMA */
 #define LTQ_DMA_BASE_ADDR	0x1E104100
 #define LTQ_DMA_SIZE		0x800
@@ -97,6 +110,8 @@
 #define LTQ_WDT_BASE_ADDR	0x1F8803F0
 #define LTQ_WDT_SIZE		0x10
 
+#define LTQ_RST_CAUSE_WDTRST	0x20
+
 /* STP - serial to parallel conversion unit */
 #define LTQ_STP_BASE_ADDR	0x1E100BB0
 #define LTQ_STP_SIZE		0x40
@@ -121,11 +136,48 @@
 #define LTQ_MPS_BASE_ADDR	(KSEG1 + 0x1F107000)
 #define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
 
+extern __iomem void *ltq_ebu_membase;
+extern __iomem void *ltq_cgu_membase;
+
+/* ebu access */
+static inline void ltq_ebu_w32(u32 v, u32 r)
+{
+	ltq_w32(v, ltq_ebu_membase + r);
+}
+static inline u32 ltq_ebu_r32(u32 r)
+{
+	return ltq_r32(ltq_ebu_membase + r);
+}
+static inline void ltq_ebu_w32_mask(u32 c, u32 s, u32 r)
+{
+	ltq_ebu_w32((ltq_ebu_r32(r) & ~(c)) | (s), r);
+}
+
+/* cgu access */
+static inline void ltq_cgu_w32(u32 v, u32 r)
+{
+	ltq_w32(v, ltq_cgu_membase + r);
+}
+static inline u32 ltq_cgu_r32(u32 r)
+{
+	return ltq_r32(ltq_cgu_membase + r);
+}
+static inline void ltq_cgu_w32_mask(u32 c, u32 s, u32 r)
+{
+	ltq_cgu_w32((ltq_cgu_r32(r) & ~(c)) | (s), r);
+}
+
 /* request a non-gpio and set the PIO config */
-extern int  ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name);
+extern int  ltq_gpio_request(unsigned int pin, unsigned int mux,
+				unsigned int dir, const char *name);
 extern void ltq_pmu_enable(unsigned int module);
 extern void ltq_pmu_disable(unsigned int module);
+extern void ltq_cgu_enable(unsigned int clk);
+
+static inline int ltq_is_ase(void)
+{
+	return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
+}
 
 static inline int ltq_is_ar9(void)
 {
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index d417909..da9bd7d 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -39,9 +39,6 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 #else /* !CONFIG_HUGETLB_PAGE */
-# ifndef BUILD_BUG
-#  define BUILD_BUG() do { extern void __build_bug(void); __build_bug(); } while (0)
-# endif
 #define HPAGE_SHIFT	({BUILD_BUG(); 0; })
 #define HPAGE_SIZE	({BUILD_BUG(); 0; })
 #define HPAGE_MASK	({BUILD_BUG(); 0; })
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 58fe71a..d5e950a 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -8,7 +8,6 @@
  * SMP support for BMIPS
  */
 
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index a81176f..924da5e 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -69,7 +69,6 @@ SECTIONS
 	RODATA
 
 	/* writeable */
-	_sdata = .;				/* Start of data section */
 	.data : {	/* Data */
 		. = . + DATAOFFSET;		/* for CONFIG_MAPPED_KERNEL */
 
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 3fccf21..cb6b39f 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -16,8 +16,12 @@ config SOC_XWAY
 	bool "XWAY"
 	select SOC_TYPE_XWAY
 	select HW_HAS_PCI
+
+config SOC_FALCON
+	bool "FALCON"
 endchoice
 
 source "arch/mips/lantiq/xway/Kconfig"
+source "arch/mips/lantiq/falcon/Kconfig"
 
 endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index e5dae0e..7e9c69e 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devices.o
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 
 obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
+obj-$(CONFIG_SOC_FALCON) += falcon/
diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
index f3dff05..b3ec498 100644
--- a/arch/mips/lantiq/Platform
+++ b/arch/mips/lantiq/Platform
@@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ)	+= lantiq/
 cflags-$(CONFIG_LANTIQ)		+= -I$(srctree)/arch/mips/include/asm/mach-lantiq
 load-$(CONFIG_LANTIQ)		= 0xffffffff80002000
 cflags-$(CONFIG_SOC_TYPE_XWAY)	+= -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
+cflags-$(CONFIG_SOC_FALCON)	+= -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 412814f..39eef7f 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -22,6 +22,7 @@
 #include <lantiq_soc.h>
 
 #include "clk.h"
+#include "prom.h"
 
 struct clk {
 	const char *name;
@@ -46,16 +47,6 @@ static struct clk cpu_clk_generic[] = {
 	},
 };
 
-static struct resource ltq_cgu_resource = {
-	.name	= "cgu",
-	.start	= LTQ_CGU_BASE_ADDR,
-	.end	= LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-/* remapped clock register range */
-void __iomem *ltq_cgu_membase;
-
 void clk_init(void)
 {
 	cpu_clk = cpu_clk_generic;
@@ -133,21 +124,11 @@ void __init plat_time_init(void)
 {
 	struct clk *clk;
 
-	if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
-		panic("Failed to insert cgu memory");
-
-	if (request_mem_region(ltq_cgu_resource.start,
-			resource_size(&ltq_cgu_resource), "cgu") < 0)
-		panic("Failed to request cgu memory");
+	ltq_soc_init();
 
-	ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
-				resource_size(&ltq_cgu_resource));
-	if (!ltq_cgu_membase) {
-		pr_err("Failed to remap cgu memory\n");
-		unreachable();
-	}
 	clk = clk_get(0, "cpu");
 	mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
 	write_c0_compare(read_c0_count());
+	pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
 	clk_put(clk);
 }
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
index de1cb2b..7193d78 100644
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -27,12 +27,8 @@
 #include "devices.h"
 
 /* nor flash */
-static struct resource ltq_nor_resource = {
-	.name	= "nor",
-	.start	= LTQ_FLASH_START,
-	.end	= LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_nor_resource =
+	MEM_RES("nor", LTQ_FLASH_START, LTQ_FLASH_MAX);
 
 static struct platform_device ltq_nor = {
 	.name		= "ltq_nor",
@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data)
 }
 
 /* watchdog */
-static struct resource ltq_wdt_resource = {
-	.name	= "watchdog",
-	.start  = LTQ_WDT_BASE_ADDR,
-	.end    = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_wdt_resource =
+	MEM_RES("watchdog", LTQ_WDT_BASE_ADDR, LTQ_WDT_SIZE);
 
 void __init ltq_register_wdt(void)
 {
@@ -61,24 +53,14 @@ void __init ltq_register_wdt(void)
 
 /* asc ports */
 static struct resource ltq_asc0_resources[] = {
-	{
-		.name	= "asc0",
-		.start  = LTQ_ASC0_BASE_ADDR,
-		.end    = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	MEM_RES("asc0", LTQ_ASC0_BASE_ADDR, LTQ_ASC_SIZE),
 	IRQ_RES(tx, LTQ_ASC_TIR(0)),
 	IRQ_RES(rx, LTQ_ASC_RIR(0)),
 	IRQ_RES(err, LTQ_ASC_EIR(0)),
 };
 
 static struct resource ltq_asc1_resources[] = {
-	{
-		.name	= "asc1",
-		.start  = LTQ_ASC1_BASE_ADDR,
-		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	MEM_RES("asc1", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE),
 	IRQ_RES(tx, LTQ_ASC_TIR(1)),
 	IRQ_RES(rx, LTQ_ASC_RIR(1)),
 	IRQ_RES(err, LTQ_ASC_EIR(1)),
diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
index 2947bb1..18b65df 100644
--- a/arch/mips/lantiq/devices.h
+++ b/arch/mips/lantiq/devices.h
@@ -14,6 +14,10 @@
 
 #define IRQ_RES(resname, irq) \
 	{.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
+#define MEM_RES(resname, adr_start, adr_size) \
+	{ .name = resname, .flags = IORESOURCE_MEM, \
+	  .start = CPHYSADDR(adr_start), \
+	  .end = CPHYSADDR(adr_start + adr_size - 1) }
 
 extern void ltq_register_nor(struct physmap_flash_data *data);
 extern void ltq_register_wdt(void);
diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
index 972e05f..5089075 100644
--- a/arch/mips/lantiq/early_printk.c
+++ b/arch/mips/lantiq/early_printk.c
@@ -12,11 +12,13 @@
 #include <lantiq.h>
 #include <lantiq_soc.h>
 
-/* no ioremap possible at this early stage, lets use KSEG1 instead  */
-#define LTQ_ASC_BASE	KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
 #define ASC_BUF		1024
-#define LTQ_ASC_FSTAT	((u32 *)(LTQ_ASC_BASE + 0x0048))
-#define LTQ_ASC_TBUF	((u32 *)(LTQ_ASC_BASE + 0x0020))
+#define LTQ_ASC_FSTAT	((u32 *)(LTQ_EARLY_ASC + 0x0048))
+#ifdef __BIG_ENDIAN
+#define LTQ_ASC_TBUF	((u32 *)(LTQ_EARLY_ASC + 0x0020 + 3))
+#else
+#define LTQ_ASC_TBUF	((u32 *)(LTQ_EARLY_ASC + 0x0020))
+#endif
 #define TXMASK		0x3F00
 #define TXOFFSET	8
 
@@ -27,7 +29,7 @@ void prom_putchar(char c)
 	local_irq_save(flags);
 	do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
 	if (c == '\n')
-		ltq_w32('\r', LTQ_ASC_TBUF);
-	ltq_w32(c, LTQ_ASC_TBUF);
+		ltq_w8('\r', LTQ_ASC_TBUF);
+	ltq_w8(c, LTQ_ASC_TBUF);
 	local_irq_restore(flags);
 }
diff --git a/arch/mips/lantiq/falcon/Kconfig b/arch/mips/lantiq/falcon/Kconfig
new file mode 100644
index 0000000..03e999d
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -0,0 +1,11 @@
+if SOC_FALCON
+
+menu "MIPS Machine"
+
+config LANTIQ_MACH_EASY98000
+	bool "Easy98000"
+	default y
+
+endmenu
+
+endif
diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
new file mode 100644
index 0000000..56b22eb
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -0,0 +1,2 @@
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
diff --git a/arch/mips/lantiq/falcon/clk.c b/arch/mips/lantiq/falcon/clk.c
new file mode 100644
index 0000000..afe1b52
--- /dev/null
+++ b/arch/mips/lantiq/falcon/clk.c
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+/* CPU0 Clock Control Register */
+#define LTQ_SYS1_CPU0CC		0x0040
+/* clock divider bit */
+#define LTQ_CPU0CC_CPUDIV	0x0001
+
+unsigned int
+ltq_get_io_region_clock(void)
+{
+	return CLOCK_200M;
+}
+EXPORT_SYMBOL(ltq_get_io_region_clock);
+
+unsigned int
+ltq_get_cpu_hz(void)
+{
+	if (ltq_sys1_r32(LTQ_SYS1_CPU0CC) & LTQ_CPU0CC_CPUDIV)
+		return CLOCK_200M;
+	else
+		return CLOCK_400M;
+}
+EXPORT_SYMBOL(ltq_get_cpu_hz);
+
+unsigned int
+ltq_get_fpi_hz(void)
+{
+	return CLOCK_100M;
+}
+EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
new file mode 100644
index 0000000..4f47b44
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -0,0 +1,128 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/nand.h>
+#include <linux/gpio.h>
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+/* nand flash */
+/* address lines used for NAND control signals */
+#define NAND_ADDR_ALE		0x10000
+#define NAND_ADDR_CLE		0x20000
+/* Ready/Busy Status */
+#define MODCON_STS		0x0002
+/* Ready/Busy Status Edge */
+#define MODCON_STSEDGE		0x0004
+
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+static int
+falcon_nand_ready(struct mtd_info *mtd)
+{
+	u32 modcon = ltq_ebu_r32(LTQ_EBU_MODCON);
+
+	return (((modcon & (MODCON_STS | MODCON_STSEDGE)) ==
+						(MODCON_STS | MODCON_STSEDGE)));
+}
+
+static void
+falcon_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+	unsigned long nandaddr = (unsigned long) this->IO_ADDR_W;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		nandaddr &= ~(NAND_ADDR_ALE | NAND_ADDR_CLE);
+
+		if (ctrl & NAND_CLE)
+			nandaddr |= NAND_ADDR_CLE;
+		if (ctrl & NAND_ALE)
+			nandaddr |= NAND_ADDR_ALE;
+
+		this->IO_ADDR_W = (void __iomem *) nandaddr;
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, this->IO_ADDR_W);
+}
+
+static struct platform_nand_data falcon_flash_nand_data = {
+	.chip = {
+		.nr_chips		= 1,
+		.chip_delay		= 25,
+		.part_probe_types	= part_probes,
+	},
+	.ctrl = {
+		.cmd_ctrl		= falcon_hwcontrol,
+		.dev_ready		= falcon_nand_ready,
+	}
+};
+
+static struct resource ltq_nand_res =
+	MEM_RES("nand", LTQ_FLASH_START, LTQ_FLASH_MAX);
+
+static struct platform_device ltq_flash_nand = {
+	.name		= "gen_nand",
+	.id		= -1,
+	.num_resources	= 1,
+	.resource	= &ltq_nand_res,
+	.dev		= {
+		.platform_data = &falcon_flash_nand_data,
+	},
+};
+
+void __init
+falcon_register_nand(void)
+{
+	platform_device_register(&ltq_flash_nand);
+}
+
+/* gpio */
+#define DECLARE_GPIO_RES(port) \
+static struct resource falcon_gpio ## port ## _res[] = { \
+	MEM_RES("gpio"#port, LTQ_GPIO ## port ## _BASE_ADDR, \
+		LTQ_GPIO ## port ## _SIZE), \
+	MEM_RES("padctrl"#port, LTQ_PADCTRL ## port ## _BASE_ADDR, \
+		LTQ_PADCTRL ## port ## _SIZE), \
+	IRQ_RES("gpio_mux"#port, FALCON_IRQ_GPIO_P ## port) \
+}
+DECLARE_GPIO_RES(0);
+DECLARE_GPIO_RES(1);
+DECLARE_GPIO_RES(2);
+DECLARE_GPIO_RES(3);
+DECLARE_GPIO_RES(4);
+
+void __init
+falcon_register_gpio(void)
+{
+	platform_device_register_simple("falcon_gpio", 0,
+		falcon_gpio0_res, ARRAY_SIZE(falcon_gpio0_res));
+	platform_device_register_simple("falcon_gpio", 1,
+		falcon_gpio1_res, ARRAY_SIZE(falcon_gpio1_res));
+	platform_device_register_simple("falcon_gpio", 2,
+		falcon_gpio2_res, ARRAY_SIZE(falcon_gpio2_res));
+	ltq_sysctl_activate(SYSCTL_SYS1, ACTS_PADCTRL1 | ACTS_P1);
+	ltq_sysctl_activate(SYSCTL_SYSETH, ACTS_PADCTRL0 |
+		ACTS_PADCTRL2 | ACTS_P0 | ACTS_P2);
+}
+
+void __init
+falcon_register_gpio_extra(void)
+{
+	platform_device_register_simple("falcon_gpio", 3,
+		falcon_gpio3_res, ARRAY_SIZE(falcon_gpio3_res));
+	platform_device_register_simple("falcon_gpio", 4,
+		falcon_gpio4_res, ARRAY_SIZE(falcon_gpio4_res));
+	ltq_sysctl_activate(SYSCTL_SYS1,
+		ACTS_PADCTRL3 | ACTS_PADCTRL4 | ACTS_P3 | ACTS_P4);
+}
diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
new file mode 100644
index 0000000..18be8b6
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -0,0 +1,20 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _FALCON_DEVICES_H__
+#define _FALCON_DEVICES_H__
+
+#include "../devices.h"
+
+extern void falcon_register_nand(void);
+extern void falcon_register_gpio(void);
+extern void falcon_register_gpio_extra(void);
+
+#endif
diff --git a/arch/mips/lantiq/falcon/gpio.c b/arch/mips/lantiq/falcon/gpio.c
new file mode 100644
index 0000000..3eebd51
--- /dev/null
+++ b/arch/mips/lantiq/falcon/gpio.c
@@ -0,0 +1,399 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+
+#include <lantiq_soc.h>
+
+/* Multiplexer Control Register */
+#define LTQ_PADC_MUX(x)         ((x) * 0x4)
+/* Pad Control Availability Register */
+#define LTQ_PADC_AVAIL          0x000000F0
+
+/* Data Output Register */
+#define LTQ_GPIO_OUT            0x00000000
+/* Data Input Register */
+#define LTQ_GPIO_IN             0x00000004
+/* Direction Register */
+#define LTQ_GPIO_DIR            0x00000008
+/* External Interrupt Control Register 0 */
+#define LTQ_GPIO_EXINTCR0       0x00000018
+/* External Interrupt Control Register 1 */
+#define LTQ_GPIO_EXINTCR1       0x0000001C
+/* IRN Capture Register */
+#define LTQ_GPIO_IRNCR          0x00000020
+/* IRN Interrupt Configuration Register */
+#define LTQ_GPIO_IRNCFG		0x0000002C
+/* IRN Interrupt Enable Set Register */
+#define LTQ_GPIO_IRNRNSET       0x00000030
+/* IRN Interrupt Enable Clear Register */
+#define LTQ_GPIO_IRNENCLR       0x00000034
+/* Output Set Register */
+#define LTQ_GPIO_OUTSET         0x00000040
+/* Output Cler Register */
+#define LTQ_GPIO_OUTCLR         0x00000044
+/* Direction Clear Register */
+#define LTQ_GPIO_DIRSET         0x00000048
+/* Direction Set Register */
+#define LTQ_GPIO_DIRCLR         0x0000004C
+
+/* turn a gpio_chip into a falcon_gpio_port */
+#define ctop(c)		container_of(c, struct falcon_gpio_port, gpio_chip)
+/* turn a irq_data into a falcon_gpio_port */
+#define itop(i)		((struct falcon_gpio_port *) irq_get_chip_data(i->irq))
+
+#define ltq_pad_r32(p, reg)		ltq_r32(p->pad + reg)
+#define ltq_pad_w32(p, val, reg)	ltq_w32(val, p->pad + reg)
+#define ltq_pad_w32_mask(c, clear, set, reg) \
+		ltq_pad_w32(c, (ltq_pad_r32(c, reg) & ~(clear)) | (set), reg)
+
+#define ltq_port_r32(p, reg)		ltq_r32(p->port + reg)
+#define ltq_port_w32(p, val, reg)	ltq_w32(val, p->port + reg)
+#define ltq_port_w32_mask(p, clear, set, reg) \
+		ltq_port_w32(p, (ltq_port_r32(p, reg) & ~(clear)) | (set), reg)
+
+#define MAX_PORTS		5
+#define PINS_PER_PORT		32
+
+struct falcon_gpio_port {
+	struct gpio_chip gpio_chip;
+	void __iomem *pad;
+	void __iomem *port;
+	unsigned int irq_base;
+	unsigned int chained_irq;
+};
+
+static struct falcon_gpio_port ltq_gpio_port[MAX_PORTS];
+
+int gpio_to_irq(unsigned int gpio)
+{
+	return __gpio_to_irq(gpio);
+}
+EXPORT_SYMBOL(gpio_to_irq);
+
+int ltq_gpio_mux_set(unsigned int pin, unsigned int mux)
+{
+	int port = pin / 100;
+	int offset = pin % 100;
+	struct falcon_gpio_port *gpio_port;
+
+	if ((offset >= PINS_PER_PORT) || (port >= MAX_PORTS))
+		return -EINVAL;
+
+	gpio_port = &ltq_gpio_port[port];
+	ltq_pad_w32(gpio_port, mux & 0x3, LTQ_PADC_MUX(offset));
+
+	return 0;
+}
+EXPORT_SYMBOL(ltq_gpio_mux_set);
+
+int ltq_gpio_request(unsigned int pin, unsigned int mux,
+			unsigned int dir, const char *name)
+{
+	int port = pin / 100;
+	int offset = pin % 100;
+
+	if (offset >= PINS_PER_PORT || port >= MAX_PORTS)
+		return -EINVAL;
+
+	if (gpio_request(pin, name)) {
+		pr_err("failed to setup lantiq gpio: %s\n", name);
+		return -EBUSY;
+	}
+
+	if (dir)
+		gpio_direction_output(pin, 1);
+	else
+		gpio_direction_input(pin);
+
+	return ltq_gpio_mux_set(pin, mux);
+}
+EXPORT_SYMBOL(ltq_gpio_request);
+
+static int
+falcon_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+	ltq_port_w32(ctop(chip), 1 << offset, LTQ_GPIO_DIRCLR);
+
+	return 0;
+}
+
+static void
+falcon_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
+{
+	if (value)
+		ltq_port_w32(ctop(chip), 1 << offset, LTQ_GPIO_OUTSET);
+	else
+		ltq_port_w32(ctop(chip), 1 << offset, LTQ_GPIO_OUTCLR);
+}
+
+static int
+falcon_gpio_direction_output(struct gpio_chip *chip,
+			unsigned int offset, int value)
+{
+	falcon_gpio_set(chip, offset, value);
+	ltq_port_w32(ctop(chip), 1 << offset, LTQ_GPIO_DIRSET);
+
+	return 0;
+}
+
+static int
+falcon_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	if ((ltq_port_r32(ctop(chip), LTQ_GPIO_DIR) >> offset) & 1)
+		return (ltq_port_r32(ctop(chip), LTQ_GPIO_OUT) >> offset) & 1;
+	else
+		return (ltq_port_r32(ctop(chip), LTQ_GPIO_IN) >> offset) & 1;
+}
+
+static int
+falcon_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	if ((ltq_pad_r32(ctop(chip), LTQ_PADC_AVAIL) >> offset) & 1) {
+		if (ltq_pad_r32(ctop(chip), LTQ_PADC_MUX(offset)) > 1)
+			return -EBUSY;
+		/* switch on gpio function */
+		ltq_pad_w32(ctop(chip), 1, LTQ_PADC_MUX(offset));
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void
+falcon_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	if ((ltq_pad_r32(ctop(chip), LTQ_PADC_AVAIL) >> offset) & 1) {
+		if (ltq_pad_r32(ctop(chip), LTQ_PADC_MUX(offset)) > 1)
+			return;
+		/* switch off gpio function */
+		ltq_pad_w32(ctop(chip), 0, LTQ_PADC_MUX(offset));
+	}
+}
+
+static int
+falcon_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	return ctop(chip)->irq_base + offset;
+}
+
+static void
+falcon_gpio_disable_irq(struct irq_data *d)
+{
+	unsigned int offset = d->irq - itop(d)->irq_base;
+
+	ltq_port_w32(itop(d), 1 << offset, LTQ_GPIO_IRNENCLR);
+}
+
+static void
+falcon_gpio_enable_irq(struct irq_data *d)
+{
+	unsigned int offset = d->irq - itop(d)->irq_base;
+
+	if (!ltq_pad_r32(itop(d), LTQ_PADC_MUX(offset)) < 1)
+		/* switch on gpio function */
+		ltq_pad_w32(itop(d), 1, LTQ_PADC_MUX(offset));
+
+	ltq_port_w32(itop(d), 1 << offset, LTQ_GPIO_IRNRNSET);
+}
+
+static void
+falcon_gpio_ack_irq(struct irq_data *d)
+{
+	unsigned int offset = d->irq - itop(d)->irq_base;
+
+	ltq_port_w32(itop(d), 1 << offset, LTQ_GPIO_IRNCR);
+}
+
+static void
+falcon_gpio_mask_and_ack_irq(struct irq_data *d)
+{
+	unsigned int offset = d->irq - itop(d)->irq_base;
+
+	ltq_port_w32(itop(d), 1 << offset, LTQ_GPIO_IRNENCLR);
+	ltq_port_w32(itop(d), 1 << offset, LTQ_GPIO_IRNCR);
+}
+
+static struct irq_chip falcon_gpio_irq_chip;
+static int
+falcon_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int offset = d->irq - itop(d)->irq_base;
+	unsigned int mask = 1 << offset;
+
+	if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_NONE)
+		return 0;
+
+	if ((type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) != 0) {
+		/* level triggered */
+		ltq_port_w32_mask(itop(d), 0, mask, LTQ_GPIO_IRNCFG);
+		irq_set_chip_and_handler_name(d->irq,
+				&falcon_gpio_irq_chip, handle_level_irq, "mux");
+	} else {
+		/* edge triggered */
+		ltq_port_w32_mask(itop(d), mask, 0, LTQ_GPIO_IRNCFG);
+		irq_set_chip_and_handler_name(d->irq,
+			&falcon_gpio_irq_chip, handle_simple_irq, "mux");
+	}
+
+	if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+		ltq_port_w32_mask(itop(d), mask, 0, LTQ_GPIO_EXINTCR0);
+		ltq_port_w32_mask(itop(d), 0, mask, LTQ_GPIO_EXINTCR1);
+	} else {
+		if ((type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH)) != 0)
+			/* positive logic: rising edge, high level */
+			ltq_port_w32_mask(itop(d), mask, 0, LTQ_GPIO_EXINTCR0);
+		else
+			/* negative logic: falling edge, low level */
+			ltq_port_w32_mask(itop(d), 0, mask, LTQ_GPIO_EXINTCR0);
+		ltq_port_w32_mask(itop(d), mask, 0, LTQ_GPIO_EXINTCR1);
+	}
+
+	return gpio_direction_input(itop(d)->gpio_chip.base + offset);
+}
+
+static void
+falcon_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct falcon_gpio_port *gpio_port = irq_desc_get_handler_data(desc);
+	unsigned long irncr;
+	int offset;
+
+	/* acknowledge interrupt */
+	irncr = ltq_port_r32(gpio_port, LTQ_GPIO_IRNCR);
+	ltq_port_w32(gpio_port, irncr, LTQ_GPIO_IRNCR);
+
+	desc->irq_data.chip->irq_ack(&desc->irq_data);
+
+	for_each_set_bit(offset, &irncr, gpio_port->gpio_chip.ngpio)
+		generic_handle_irq(gpio_port->irq_base + offset);
+}
+
+static struct irq_chip falcon_gpio_irq_chip = {
+	.name = "gpio_irq_mux",
+	.irq_mask = falcon_gpio_disable_irq,
+	.irq_unmask = falcon_gpio_enable_irq,
+	.irq_ack = falcon_gpio_ack_irq,
+	.irq_mask_ack = falcon_gpio_mask_and_ack_irq,
+	.irq_set_type = falcon_gpio_irq_type,
+};
+
+static struct irqaction gpio_cascade = {
+	.handler = no_action,
+	.flags = IRQF_DISABLED,
+	.name = "gpio_cascade",
+};
+
+static int
+falcon_gpio_probe(struct platform_device *pdev)
+{
+	struct falcon_gpio_port *gpio_port;
+	int ret, i;
+	struct resource *gpiores, *padres;
+	int irq;
+
+	if (pdev->id >= MAX_PORTS)
+		return -ENODEV;
+
+	gpiores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	padres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irq = platform_get_irq(pdev, 0);
+	if (!gpiores || !padres)
+		return -ENODEV;
+
+	gpio_port = &ltq_gpio_port[pdev->id];
+	gpio_port->gpio_chip.label = "falcon-gpio";
+	gpio_port->gpio_chip.direction_input = falcon_gpio_direction_input;
+	gpio_port->gpio_chip.direction_output = falcon_gpio_direction_output;
+	gpio_port->gpio_chip.get = falcon_gpio_get;
+	gpio_port->gpio_chip.set = falcon_gpio_set;
+	gpio_port->gpio_chip.request = falcon_gpio_request;
+	gpio_port->gpio_chip.free = falcon_gpio_free;
+	gpio_port->gpio_chip.base = 100 * pdev->id;
+	gpio_port->gpio_chip.ngpio = 32;
+	gpio_port->gpio_chip.dev = &pdev->dev;
+
+	gpio_port->port = ltq_remap_resource(gpiores);
+	gpio_port->pad = ltq_remap_resource(padres);
+
+	if (!gpio_port->port || !gpio_port->pad) {
+		dev_err(&pdev->dev, "Could not map io ranges\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (irq > 0) {
+		/* irq_chip support */
+		gpio_port->gpio_chip.to_irq = falcon_gpio_to_irq;
+		gpio_port->irq_base = INT_NUM_EXTRA_START + (32 * pdev->id);
+
+		for (i = 0; i < 32; i++) {
+			irq_set_chip_and_handler_name(gpio_port->irq_base + i,
+				&falcon_gpio_irq_chip, handle_simple_irq,
+				"mux");
+			irq_set_chip_data(gpio_port->irq_base + i, gpio_port);
+			/* set to negative logic (falling edge, low level) */
+			ltq_port_w32_mask(gpio_port, 0, 1 << i,
+				LTQ_GPIO_EXINTCR0);
+		}
+
+		gpio_port->chained_irq = irq;
+		setup_irq(irq, &gpio_cascade);
+		irq_set_handler_data(irq, gpio_port);
+		irq_set_chained_handler(irq, falcon_gpio_irq_handler);
+	}
+
+	ret = gpiochip_add(&gpio_port->gpio_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip %d, %d\n",
+			pdev->id, ret);
+		goto err;
+	}
+	platform_set_drvdata(pdev, gpio_port);
+	return ret;
+
+err:
+	dev_err(&pdev->dev, "Error in gpio_probe %d, %d\n", pdev->id, ret);
+	if (gpiores)
+		release_resource(gpiores);
+	if (padres)
+		release_resource(padres);
+
+	if (gpio_port->port)
+		iounmap(gpio_port->port);
+	if (gpio_port->pad)
+		iounmap(gpio_port->pad);
+	return ret;
+}
+
+static struct platform_driver falcon_gpio_driver = {
+	.probe = falcon_gpio_probe,
+	.driver = {
+		.name = "falcon_gpio",
+		.owner = THIS_MODULE,
+	},
+};
+
+int __init
+falcon_gpio_init(void)
+{
+	int ret;
+
+	pr_info("FALC(tm) ON GPIO Driver, (C) 2011 Lantiq Deutschland Gmbh\n");
+	ret = platform_driver_register(&falcon_gpio_driver);
+	if (ret)
+		pr_err("falcon_gpio: Error registering platform driver!");
+	return ret;
+}
+
+postcore_initcall(falcon_gpio_init);
diff --git a/arch/mips/lantiq/falcon/mach-easy98000.c b/arch/mips/lantiq/falcon/mach-easy98000.c
new file mode 100644
index 0000000..361b8f0
--- /dev/null
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
@@ -0,0 +1,110 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/eeprom.h>
+
+#include "../machtypes.h"
+
+#include "devices.h"
+
+static struct mtd_partition easy98000_nor_partitions[] = {
+	{
+		.name	= "uboot",
+		.offset	= 0x0,
+		.size	= 0x40000,
+	},
+	{
+		.name	= "uboot_env",
+		.offset	= 0x40000,
+		.size	= 0x40000,	/* 2 sectors for redundant env. */
+	},
+	{
+		.name	= "linux",
+		.offset	= 0x80000,
+		.size	= 0xF80000,	/* map only 16 MiB */
+	},
+};
+
+struct physmap_flash_data easy98000_nor_flash_data = {
+	.nr_parts	= ARRAY_SIZE(easy98000_nor_partitions),
+	.parts		= easy98000_nor_partitions,
+};
+
+/* setup gpio based spi bus/device for access to the eeprom on the board */
+#define SPI_GPIO_MRST		102
+#define SPI_GPIO_MTSR		103
+#define SPI_GPIO_CLK		104
+#define SPI_GPIO_CS0		105
+#define SPI_GPIO_CS1		106
+#define SPI_GPIO_BUS_NUM	1
+
+static struct spi_gpio_platform_data easy98000_spi_gpio_data = {
+	.sck		= SPI_GPIO_CLK,
+	.mosi		= SPI_GPIO_MTSR,
+	.miso		= SPI_GPIO_MRST,
+	.num_chipselect	= 2,
+};
+
+static struct platform_device easy98000_spi_gpio_device = {
+	.name			= "spi_gpio",
+	.id			= SPI_GPIO_BUS_NUM,
+	.dev.platform_data	= &easy98000_spi_gpio_data,
+};
+
+static struct spi_eeprom at25160n = {
+	.byte_len	= 16 * 1024 / 8,
+	.name		= "at25160n",
+	.page_size	= 32,
+	.flags		= EE_ADDR2,
+};
+
+static struct spi_board_info easy98000_spi_gpio_devices __initdata = {
+	.modalias		= "at25",
+	.bus_num		= SPI_GPIO_BUS_NUM,
+	.max_speed_hz		= 1000 * 1000,
+	.mode			= SPI_MODE_3,
+	.chip_select		= 1,
+	.controller_data	= (void *) SPI_GPIO_CS1,
+	.platform_data		= &at25160n,
+};
+
+static void __init
+easy98000_init_common(void)
+{
+	spi_register_board_info(&easy98000_spi_gpio_devices, 1);
+	platform_device_register(&easy98000_spi_gpio_device);
+}
+
+static void __init
+easy98000_init(void)
+{
+	easy98000_init_common();
+	ltq_register_nor(&easy98000_nor_flash_data);
+}
+
+static void __init
+easy98000nand_init(void)
+{
+	easy98000_init_common();
+	falcon_register_nand();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_EASY98000,
+			"EASY98000",
+			"EASY98000 Eval Board",
+			easy98000_init);
+
+MIPS_MACHINE(LANTIQ_MACH_EASY98000NAND,
+			"EASY98000NAND",
+			"EASY98000 Eval Board (NAND Flash)",
+			easy98000nand_init);
diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
new file mode 100644
index 0000000..b50d6f9
--- /dev/null
+++ b/arch/mips/lantiq/falcon/prom.c
@@ -0,0 +1,93 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+#include "../prom.h"
+
+#define SOC_FALCON		"Falcon"
+#define SOC_FALCON_D		"Falcon-D"
+#define SOC_FALCON_V		"Falcon-V"
+#define SOC_FALCON_M		"Falcon-M"
+
+#define PART_SHIFT	12
+#define PART_MASK	0x0FFFF000
+#define REV_SHIFT	28
+#define REV_MASK	0xF0000000
+#define SREV_SHIFT	22
+#define SREV_MASK	0x03C00000
+#define TYPE_SHIFT	26
+#define TYPE_MASK	0x3C000000
+
+#define MUXC_SIF_RX_PIN		112
+#define MUXC_SIF_TX_PIN		113
+
+/* this parameter allows us enable/disable asc1 via commandline */
+static int register_asc1;
+static int __init
+ltq_parse_asc1(char *p)
+{
+	register_asc1 = 1;
+	return 0;
+}
+__setup("use_asc1", ltq_parse_asc1);
+
+void __init
+ltq_soc_setup(void)
+{
+	ltq_register_asc(0);
+	ltq_register_wdt();
+	falcon_register_gpio();
+	if (register_asc1) {
+		ltq_register_asc(1);
+		if (ltq_gpio_request(MUXC_SIF_RX_PIN, 3, 0, "asc1-rx"))
+			pr_err("failed to request asc1-rx");
+		if (ltq_gpio_request(MUXC_SIF_TX_PIN, 3, 1, "asc1-tx"))
+			pr_err("failed to request asc1-tx");
+		ltq_sysctl_activate(SYSCTL_SYS1, ACTS_ASC1_ACT);
+	}
+}
+
+void __init
+ltq_soc_detect(struct ltq_soc_info *i)
+{
+	u32 type;
+	i->partnum = (ltq_r32(LTQ_FALCON_CHIPID) & PART_MASK) >> PART_SHIFT;
+	i->rev = (ltq_r32(LTQ_FALCON_CHIPID) & REV_MASK) >> REV_SHIFT;
+	i->srev = ((ltq_r32(LTQ_FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT);
+	sprintf(i->rev_type, "%c%d%d", (i->srev & 0x4) ? ('B') : ('A'),
+		i->rev & 0x7, (i->srev & 0x3) + 1);
+
+	switch (i->partnum) {
+	case SOC_ID_FALCON:
+		type = (ltq_r32(LTQ_FALCON_CHIPTYPE) & TYPE_MASK) >> TYPE_SHIFT;
+		switch (type) {
+		case 0:
+			i->name = SOC_FALCON_D;
+			break;
+		case 1:
+			i->name = SOC_FALCON_V;
+			break;
+		case 2:
+			i->name = SOC_FALCON_M;
+			break;
+		default:
+			i->name = SOC_FALCON;
+			break;
+		}
+		i->type = SOC_TYPE_FALCON;
+		break;
+
+	default:
+		unreachable();
+		break;
+	}
+}
diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c
new file mode 100644
index 0000000..6d829af
--- /dev/null
+++ b/arch/mips/lantiq/falcon/reset.c
@@ -0,0 +1,88 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <asm/reboot.h>
+#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
+/* CPU0 Reset Source Register */
+#define LTQ_SYS1_CPU0RS		0x0040
+/* reset cause mask */
+#define LTQ_CPU0RS_MASK		0x0003
+
+int
+ltq_reset_cause(void)
+{
+	return ltq_sys1_r32(LTQ_SYS1_CPU0RS) & LTQ_CPU0RS_MASK;
+}
+EXPORT_SYMBOL_GPL(ltq_reset_cause);
+
+#define BOOT_REG_BASE	(KSEG1 | 0x1F200000)
+#define BOOT_PW1_REG	(BOOT_REG_BASE | 0x20)
+#define BOOT_PW2_REG	(BOOT_REG_BASE | 0x24)
+#define BOOT_PW1	0x4C545100
+#define BOOT_PW2	0x0051544C
+
+#define WDT_REG_BASE	(KSEG1 | 0x1F8803F0)
+#define WDT_PW1		0x00BE0000
+#define WDT_PW2		0x00DC0000
+
+static void
+ltq_machine_restart(char *command)
+{
+	local_irq_disable();
+
+	/* reboot magic */
+	ltq_w32(BOOT_PW1, (void *)BOOT_PW1_REG); /* 'LTQ\0' */
+	ltq_w32(BOOT_PW2, (void *)BOOT_PW2_REG); /* '\0QTL' */
+	ltq_w32(0, (void *)BOOT_REG_BASE); /* reset Bootreg RVEC */
+
+	/* watchdog magic */
+	ltq_w32(WDT_PW1, (void *)WDT_REG_BASE);
+	ltq_w32(WDT_PW2 |
+		(0x3 << 26) | /* PWL */
+		(0x2 << 24) | /* CLKDIV */
+		(0x1 << 31) | /* enable */
+		(1), /* reload */
+		(void *)WDT_REG_BASE);
+	/*
+	 * Dont call unreachable(); here as we need to wait for the watchdog
+	 * to trigger.
+	 */
+	do {} while (1);
+}
+
+static void
+ltq_machine_halt(void)
+{
+	local_irq_disable();
+	unreachable();
+}
+
+static void
+ltq_machine_power_off(void)
+{
+	local_irq_disable();
+	unreachable();
+}
+
+static int __init
+mips_reboot_setup(void)
+{
+	_machine_restart = ltq_machine_restart;
+	_machine_halt = ltq_machine_halt;
+	pm_power_off = ltq_machine_power_off;
+	return 0;
+}
+
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
new file mode 100644
index 0000000..905a142
--- /dev/null
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -0,0 +1,183 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/export.h>
+#include <asm/delay.h>
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+/* infrastructure control register */
+#define SYS1_INFRAC		0x00bc
+/* Configuration fuses for drivers and pll */
+#define STATUS_CONFIG		0x0040
+
+/* GPE frequency selection */
+#define GPPC_OFFSET		24
+#define GPEFREQ_MASK		0x00000C0
+#define GPEFREQ_OFFSET		10
+/* Clock status register */
+#define LTQ_SYSCTL_CLKS		0x0000
+/* Clock enable register */
+#define LTQ_SYSCTL_CLKEN	0x0004
+/* Clock clear register */
+#define LTQ_SYSCTL_CLKCLR	0x0008
+/* Activation Status Register */
+#define LTQ_SYSCTL_ACTS		0x0020
+/* Activation Register */
+#define LTQ_SYSCTL_ACT		0x0024
+/* Deactivation Register */
+#define LTQ_SYSCTL_DEACT	0x0028
+/* reboot Register */
+#define LTQ_SYSCTL_RBT		0x002c
+
+static struct resource ltq_sysctl_res[] = {
+	MEM_RES("sys1", LTQ_SYS1_BASE_ADDR, LTQ_SYS1_SIZE),
+	MEM_RES("syseth", LTQ_SYS_ETH_BASE_ADDR, LTQ_SYS_ETH_SIZE),
+	MEM_RES("sysgpe", LTQ_SYS_GPE_BASE_ADDR, LTQ_SYS_GPE_SIZE),
+};
+
+static struct resource ltq_status_res =
+	MEM_RES("status", LTQ_STATUS_BASE_ADDR, LTQ_STATUS_SIZE);
+static struct resource ltq_ebu_res =
+	MEM_RES("ebu", LTQ_EBU_BASE_ADDR, LTQ_EBU_SIZE);
+
+static void __iomem *ltq_sysctl[3];
+static void __iomem *ltq_status_membase;
+void __iomem *ltq_sys1_membase;
+void __iomem *ltq_ebu_membase;
+
+#define ltq_reg_w32(m, x, y)	ltq_w32((x), ltq_sysctl[m] + (y))
+#define ltq_reg_r32(m, x)	ltq_r32(ltq_sysctl[m] + (x))
+#define ltq_reg_w32_mask(m, clear, set, reg)	\
+		ltq_reg_w32(m, (ltq_reg_r32(m, reg) & ~(clear)) | (set), reg)
+
+#define ltq_status_w32(x, y)	ltq_w32((x), ltq_status_membase + (y))
+#define ltq_status_r32(x)	ltq_r32(ltq_status_membase + (x))
+
+static inline void
+ltq_sysctl_wait(int module, unsigned int mask,
+		unsigned int test, unsigned int reg)
+{
+	int err = 1000000;
+
+	do {} while (--err && ((ltq_reg_r32(module, reg)
+					& mask) != test));
+	if (!err)
+		pr_err("module de/activation failed %d %08X %08X\n",
+							module, mask, test);
+}
+
+void
+ltq_sysctl_activate(int module, unsigned int mask)
+{
+	if (module > SYSCTL_SYSGPE)
+		return;
+
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_ACT);
+	ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_activate);
+
+void
+ltq_sysctl_deactivate(int module, unsigned int mask)
+{
+	if (module > SYSCTL_SYSGPE)
+		return;
+
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_DEACT);
+	ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_deactivate);
+
+void
+ltq_sysctl_clken(int module, unsigned int mask)
+{
+	if (module > SYSCTL_SYSGPE)
+		return;
+
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
+	ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_CLKS);
+}
+EXPORT_SYMBOL(ltq_sysctl_clken);
+
+void
+ltq_sysctl_clkdis(int module, unsigned int mask)
+{
+	if (module > SYSCTL_SYSGPE)
+		return;
+
+	ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
+	ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_CLKS);
+}
+EXPORT_SYMBOL(ltq_sysctl_clkdis);
+
+void
+ltq_sysctl_reboot(int module, unsigned int mask)
+{
+	unsigned int act;
+
+	if (module > SYSCTL_SYSGPE)
+		return;
+
+	act = ltq_reg_r32(module, LTQ_SYSCTL_ACT);
+	if ((~act & mask) != 0)
+		ltq_sysctl_activate(module, ~act & mask);
+	ltq_reg_w32(module, act & mask, LTQ_SYSCTL_RBT);
+	ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_reboot);
+
+/* enable the ONU core */
+static void
+ltq_gpe_enable(void)
+{
+	unsigned int freq;
+	unsigned int status;
+
+	/* if if the clock is already enabled */
+	status = ltq_reg_r32(SYSCTL_SYS1, SYS1_INFRAC);
+	if (status & (1 << (GPPC_OFFSET + 1)))
+		return;
+
+	if (ltq_status_r32(STATUS_CONFIG) == 0)
+		freq = 1; /* use 625MHz on unfused chip */
+	else
+		freq = (ltq_status_r32(STATUS_CONFIG) &
+			GPEFREQ_MASK) >>
+			GPEFREQ_OFFSET;
+
+	/* apply new frequency */
+	ltq_reg_w32_mask(SYSCTL_SYS1, 7 << (GPPC_OFFSET + 1),
+		freq << (GPPC_OFFSET + 2) , SYS1_INFRAC);
+	udelay(1);
+
+	/* enable new frequency */
+	ltq_reg_w32_mask(SYSCTL_SYS1, 0, 1 << (GPPC_OFFSET + 1), SYS1_INFRAC);
+	udelay(1);
+}
+
+void __init
+ltq_soc_init(void)
+{
+	int i;
+
+	for (i = 0; i < 3; i++)
+		ltq_sysctl[i] = ltq_remap_resource(&ltq_sysctl_res[i]);
+
+	ltq_sys1_membase = ltq_sysctl[0];
+	ltq_status_membase = ltq_remap_resource(&ltq_status_res);
+	ltq_ebu_membase = ltq_remap_resource(&ltq_ebu_res);
+
+	ltq_gpe_enable();
+}
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index d673731..3b8cea5 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -195,7 +195,7 @@ static void ltq_hw_irqdispatch(int module)
 	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
 
 	/* if this is a EBU irq, we need to ack it or get a deadlock */
-	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
+	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
 		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
 			LTQ_EBU_PCC_ISTAT);
 }
@@ -259,17 +259,19 @@ void __init arch_init_irq(void)
 	if (!ltq_icu_membase)
 		panic("Failed to remap icu memory");
 
-	if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
-		panic("Failed to insert eiu memory");
+	if (LTQ_EIU_BASE_ADDR) {
+		if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
+			panic("Failed to insert eiu memory");
 
-	if (request_mem_region(ltq_eiu_resource.start,
-			resource_size(&ltq_eiu_resource), "eiu") < 0)
-		panic("Failed to request eiu memory");
+		if (request_mem_region(ltq_eiu_resource.start,
+				resource_size(&ltq_eiu_resource), "eiu") < 0)
+			panic("Failed to request eiu memory");
 
-	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
+		ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
 				resource_size(&ltq_eiu_resource));
-	if (!ltq_eiu_membase)
-		panic("Failed to remap eiu memory");
+		if (!ltq_eiu_membase)
+			panic("Failed to remap eiu memory");
+	}
 
 	/* make sure all irqs are turned off by default */
 	for (i = 0; i < 5; i++)
@@ -295,8 +297,8 @@ void __init arch_init_irq(void)
 
 	for (i = INT_NUM_IRQ0;
 		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
-		if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
-			(i == LTQ_EIU_IR2))
+		if (((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) ||
+			(i == LTQ_EIU_IR2)) && LTQ_EIU_BASE_ADDR)
 			irq_set_chip_and_handler(i, &ltq_eiu_type,
 				handle_level_irq);
 		/* EIU3-5 only exist on ar9 and vr9 */
diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
index 7e01b8c..dfc6af7 100644
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -15,6 +15,11 @@ enum lantiq_mach_type {
 	LTQ_MACH_GENERIC = 0,
 	LTQ_MACH_EASY50712,	/* Danube evaluation board */
 	LTQ_MACH_EASY50601,	/* Amazon SE evaluation board */
+
+	/* FALCON */
+	LANTIQ_MACH_EASY98000,		/* Falcon Eval Board, NOR Flash */
+	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
+	LANTIQ_MACH_EASY98000NAND,	/* Falcon Eval Board, NAND Flash */
 };
 
 #endif
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index e34fcfd..ee63a33 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -16,6 +16,10 @@
 #include "prom.h"
 #include "clk.h"
 
+/* access to the ebu needs to be locked between different drivers */
+DEFINE_SPINLOCK(ebu_lock);
+EXPORT_SYMBOL_GPL(ebu_lock);
+
 static struct ltq_soc_info soc_info;
 
 unsigned int ltq_get_cpu_ver(void)
@@ -45,26 +49,63 @@ static void __init prom_init_cmdline(void)
 	char **argv = (char **) KSEG1ADDR(fw_arg1);
 	int i;
 
+	arcs_cmdline[0] = '\0';
+
 	for (i = 0; i < argc; i++) {
-		char *p = (char *)  KSEG1ADDR(argv[i]);
+		char *p = (char *) KSEG1ADDR(argv[i]);
 
-		if (p && *p) {
+		if (CPHYSADDR(p) && *p) {
 			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
 			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
 		}
 	}
 }
 
-void __init prom_init(void)
+void __iomem *ltq_remap_resource(struct resource *res)
 {
-	struct clk *clk;
+	__iomem void *ret = NULL;
+	struct resource *lookup = lookup_resource(&iomem_resource, res->start);
+
+	if (lookup && strcmp(lookup->name, res->name)) {
+		pr_err("conflicting memory range %s\n", res->name);
+		return NULL;
+	}
+	if (!lookup) {
+		if (insert_resource(&iomem_resource, res) < 0) {
+			pr_err("Failed to insert %s memory\n", res->name);
+			return NULL;
+		}
+	}
+	if (request_mem_region(res->start,
+			resource_size(res), res->name) < 0) {
+		pr_err("Failed to request %s memory\n", res->name);
+		goto err_res;
+	}
 
+	ret = ioremap_nocache(res->start, resource_size(res));
+	if (!ret)
+		goto err_mem;
+
+	pr_debug("remap: 0x%08X-0x%08X : \"%s\"\n",
+		res->start, res->end, res->name);
+	return ret;
+
+err_mem:
+	panic("Failed to remap %s memory", res->name);
+	release_mem_region(res->start, resource_size(res));
+
+err_res:
+	release_resource(res);
+	return NULL;
+}
+EXPORT_SYMBOL(ltq_remap_resource);
+
+void __init prom_init(void)
+{
 	ltq_soc_detect(&soc_info);
 	clk_init();
-	clk = clk_get(0, "cpu");
-	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
-		soc_info.name, soc_info.rev);
-	clk_put(clk);
+	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
+		soc_info.name, soc_info.rev_type);
 	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
 	pr_info("SoC: %s\n", soc_info.sys_type);
 	prom_init_cmdline();
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index b4229d9..51dba1b 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -9,17 +9,21 @@
 #ifndef _LTQ_PROM_H__
 #define _LTQ_PROM_H__
 
+#define LTQ_SYS_REV_LEN		0x10
 #define LTQ_SYS_TYPE_LEN	0x100
 
 struct ltq_soc_info {
 	unsigned char *name;
 	unsigned int rev;
+	unsigned char rev_type[LTQ_SYS_REV_LEN];
+	unsigned int srev;
 	unsigned int partnum;
 	unsigned int type;
 	unsigned char sys_type[LTQ_SYS_TYPE_LEN];
 };
 
 extern void ltq_soc_detect(struct ltq_soc_info *i);
+extern void ltq_soc_init(void);
 extern void ltq_soc_setup(void);
 
 #endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index c517f2e..6678402 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1,7 @@
-obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
+obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
 
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
+obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
 
 obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
 obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
index d614aa7..eab4644d 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -31,22 +31,9 @@
 
 /* gpio */
 static struct resource ltq_gpio_resource[] = {
-	{
-		.name	= "gpio0",
-		.start  = LTQ_GPIO0_BASE_ADDR,
-		.end    = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio1",
-		.start  = LTQ_GPIO1_BASE_ADDR,
-		.end    = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}, {
-		.name	= "gpio2",
-		.start  = LTQ_GPIO2_BASE_ADDR,
-		.end    = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	}
+	MEM_RES("gpio0", LTQ_GPIO0_BASE_ADDR, LTQ_GPIO_SIZE),
+	MEM_RES("gpio1", LTQ_GPIO1_BASE_ADDR, LTQ_GPIO_SIZE),
+	MEM_RES("gpio2", LTQ_GPIO2_BASE_ADDR, LTQ_GPIO_SIZE),
 };
 
 void __init ltq_register_gpio(void)
@@ -64,12 +51,8 @@ void __init ltq_register_gpio(void)
 }
 
 /* serial to parallel conversion */
-static struct resource ltq_stp_resource = {
-	.name   = "stp",
-	.start  = LTQ_STP_BASE_ADDR,
-	.end    = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_stp_resource =
+	MEM_RES("stp", LTQ_STP_BASE_ADDR, LTQ_STP_SIZE);
 
 void __init ltq_register_gpio_stp(void)
 {
@@ -78,12 +61,7 @@ void __init ltq_register_gpio_stp(void)
 
 /* asc ports - amazon se has its own serial mapping */
 static struct resource ltq_ase_asc_resources[] = {
-	{
-		.name	= "asc0",
-		.start  = LTQ_ASC1_BASE_ADDR,
-		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+	MEM_RES("asc0", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE),
 	IRQ_RES(tx, LTQ_ASC_ASE_TIR),
 	IRQ_RES(rx, LTQ_ASC_ASE_RIR),
 	IRQ_RES(err, LTQ_ASC_ASE_EIR),
@@ -96,22 +74,23 @@ void __init ltq_register_ase_asc(void)
 }
 
 /* ethernet */
-static struct resource ltq_etop_resources = {
-	.name	= "etop",
-	.start	= LTQ_ETOP_BASE_ADDR,
-	.end	= LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
+static struct resource ltq_etop_resources[] = {
+	MEM_RES("etop", LTQ_ETOP_BASE_ADDR, LTQ_ETOP_SIZE),
+	MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
 };
 
 static struct platform_device ltq_etop = {
 	.name		= "ltq_etop",
-	.resource	= &ltq_etop_resources,
+	.resource	= ltq_etop_resources,
 	.num_resources	= 1,
 };
 
 void __init
 ltq_register_etop(struct ltq_eth_data *eth)
 {
+	/* only register the gphy on socs that have one */
+	if (ltq_is_ar9() | ltq_is_vr9())
+		ltq_etop.num_resources = 2;
 	if (eth) {
 		ltq_etop.dev.platform_data = eth;
 		platform_device_register(&ltq_etop);
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index b210e93..6cf883b 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -24,6 +24,8 @@
 #include <lantiq_soc.h>
 #include <xway_dma.h>
 
+#include "../devices.h"
+
 #define LTQ_DMA_CTRL		0x10
 #define LTQ_DMA_CPOLL		0x14
 #define LTQ_DMA_CS		0x18
@@ -55,12 +57,8 @@
 #define ltq_dma_w32_mask(x, y, z)	ltq_w32_mask(x, y, \
 						ltq_dma_membase + (z))
 
-static struct resource ltq_dma_resource = {
-	.name	= "dma",
-	.start	= LTQ_DMA_BASE_ADDR,
-	.end	= LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_dma_resource =
+	MEM_RES("dma", LTQ_DMA_BASE_ADDR, LTQ_DMA_SIZE);
 
 static void __iomem *ltq_dma_membase;
 
@@ -220,17 +218,8 @@ ltq_dma_init(void)
 {
 	int i;
 
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
-		panic("Failed to insert dma memory");
-
-	if (request_mem_region(ltq_dma_resource.start,
-			resource_size(&ltq_dma_resource), "dma") < 0)
-		panic("Failed to request dma memory");
-
 	/* remap dma register range */
-	ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
-				resource_size(&ltq_dma_resource));
+	ltq_dma_membase = ltq_remap_resource(&ltq_dma_resource);
 	if (!ltq_dma_membase)
 		panic("Failed to remap dma memory");
 
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
deleted file mode 100644
index 862e3e8..0000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  EBU - the external bus unit attaches PCI, NOR and NAND
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-/* all access to the ebu must be locked */
-DEFINE_SPINLOCK(ebu_lock);
-EXPORT_SYMBOL_GPL(ebu_lock);
-
-static struct resource ltq_ebu_resource = {
-	.name	= "ebu",
-	.start	= LTQ_EBU_BASE_ADDR,
-	.end	= LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-/* remapped base addr of the clock unit and external bus unit */
-void __iomem *ltq_ebu_membase;
-
-static int __init lantiq_ebu_init(void)
-{
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
-		panic("Failed to insert ebu memory");
-
-	if (request_mem_region(ltq_ebu_resource.start,
-			resource_size(&ltq_ebu_resource), "ebu") < 0)
-		panic("Failed to request ebu memory");
-
-	/* remap ebu register range */
-	ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
-				resource_size(&ltq_ebu_resource));
-	if (!ltq_ebu_membase)
-		panic("Failed to remap ebu memory");
-
-	/* make sure to unprotect the memory region where flash is located */
-	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
-	return 0;
-}
-
-postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
index d2fa98f..14ff7c7 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -21,6 +21,8 @@
 #define LTQ_GPIO_ALTSEL0	0x0C
 #define LTQ_GPIO_ALTSEL1	0x10
 #define LTQ_GPIO_OD		0x14
+#define LTQ_GPIO_PUDSEL		0x1C
+#define LTQ_GPIO_PUDEN		0x20
 
 #define PINS_PER_PORT		16
 #define MAX_PORTS		3
@@ -48,8 +50,8 @@ int irq_to_gpio(unsigned int gpio)
 }
 EXPORT_SYMBOL(irq_to_gpio);
 
-int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-	unsigned int alt1, unsigned int dir, const char *name)
+int ltq_gpio_request(unsigned int pin, unsigned int mux,
+			unsigned int dir, const char *name)
 {
 	int id = 0;
 
@@ -67,13 +69,13 @@ int ltq_gpio_request(unsigned int pin, unsigned int alt0,
 		pin -= PINS_PER_PORT;
 		id++;
 	}
-	if (alt0)
+	if (mux & 0x2)
 		ltq_gpio_setbit(ltq_gpio_port[id].membase,
 			LTQ_GPIO_ALTSEL0, pin);
 	else
 		ltq_gpio_clearbit(ltq_gpio_port[id].membase,
 			LTQ_GPIO_ALTSEL0, pin);
-	if (alt1)
+	if (mux & 0x1)
 		ltq_gpio_setbit(ltq_gpio_port[id].membase,
 			LTQ_GPIO_ALTSEL1, pin);
 	else
@@ -106,6 +108,8 @@ static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 
 	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
 	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
+	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
 
 	return 0;
 }
@@ -117,6 +121,8 @@ static int ltq_gpio_direction_output(struct gpio_chip *chip,
 
 	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
 	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
+	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
 	ltq_gpio_set(chip, offset, value);
 
 	return 0;
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
index ff9991c..cb6f170 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -35,6 +35,8 @@
 #define LTQ_STP_ADSL_SRC	(3 << 24)
 
 #define LTQ_STP_GROUP0		(1 << 0)
+#define LTQ_STP_GROUP1		(1 << 1)
+#define LTQ_STP_GROUP2		(1 << 2)
 
 #define LTQ_STP_RISING		0
 #define LTQ_STP_FALLING		(1 << 26)
@@ -79,9 +81,9 @@ static struct gpio_chip ltq_stp_chip = {
 static int ltq_stp_hw_init(void)
 {
 	/* the 3 pins used to control the external stp */
-	ltq_gpio_request(4, 1, 0, 1, "stp-st");
-	ltq_gpio_request(5, 1, 0, 1, "stp-d");
-	ltq_gpio_request(6, 1, 0, 1, "stp-sh");
+	ltq_gpio_request(4, 2, 1, "stp-st");
+	ltq_gpio_request(5, 2, 1, "stp-d");
+	ltq_gpio_request(6, 2, 1, "stp-sh");
 
 	/* sane defaults */
 	ltq_stp_w32(0, LTQ_STP_AR);
@@ -93,8 +95,9 @@ static int ltq_stp_hw_init(void)
 	/* rising or falling edge */
 	ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
 
-	/* per default stp 15-0 are set */
-	ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
+	/* enable all three led groups */
+	ltq_stp_w32_mask(0, LTQ_STP_GROUP0 | LTQ_STP_GROUP1 | LTQ_STP_GROUP2,
+		LTQ_STP_CON1);
 
 	/* stp are update periodically by the FPI bus */
 	ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
index d5aaf63..16d65e0 100644
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ b/arch/mips/lantiq/xway/mach-easy50601.c
@@ -46,9 +46,14 @@ static struct physmap_flash_data easy50601_flash_data = {
 	.parts		= easy50601_partitions,
 };
 
+static struct ltq_eth_data ltq_eth_data = {
+	.mii_mode = -1, /* use EPHY */
+};
+
 static void __init easy50601_init(void)
 {
 	ltq_register_nor(&easy50601_flash_data);
+	ltq_register_etop(&ltq_eth_data);
 }
 
 MIPS_MACHINE(LTQ_MACH_EASY50601,
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
deleted file mode 100644
index fe85361..0000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
-
-/* PMU - the power management unit allows us to turn part of the core
- * on and off
- */
-
-/* the enable / disable registers */
-#define LTQ_PMU_PWDCR	0x1C
-#define LTQ_PMU_PWDSR	0x20
-
-#define ltq_pmu_w32(x, y)	ltq_w32((x), ltq_pmu_membase + (y))
-#define ltq_pmu_r32(x)		ltq_r32(ltq_pmu_membase + (x))
-
-static struct resource ltq_pmu_resource = {
-	.name	= "pmu",
-	.start	= LTQ_PMU_BASE_ADDR,
-	.end	= LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
-	.flags	= IORESOURCE_MEM,
-};
-
-static void __iomem *ltq_pmu_membase;
-
-void ltq_pmu_enable(unsigned int module)
-{
-	int err = 1000000;
-
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
-	do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
-
-	if (!err)
-		panic("activating PMU module failed!");
-}
-EXPORT_SYMBOL(ltq_pmu_enable);
-
-void ltq_pmu_disable(unsigned int module)
-{
-	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
-}
-EXPORT_SYMBOL(ltq_pmu_disable);
-
-int __init ltq_pmu_init(void)
-{
-	if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
-		panic("Failed to insert pmu memory");
-
-	if (request_mem_region(ltq_pmu_resource.start,
-			resource_size(&ltq_pmu_resource), "pmu") < 0)
-		panic("Failed to request pmu memory");
-
-	ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
-				resource_size(&ltq_pmu_resource));
-	if (!ltq_pmu_membase)
-		panic("Failed to remap pmu memory");
-	return 0;
-}
-
-core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
index ae4959a..3f86a3b 100644
--- a/arch/mips/lantiq/xway/prom-ase.c
+++ b/arch/mips/lantiq/xway/prom-ase.c
@@ -13,6 +13,7 @@
 
 #include <lantiq_soc.h>
 
+#include "devices.h"
 #include "../prom.h"
 
 #define SOC_AMAZON_SE	"Amazon_SE"
@@ -26,6 +27,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
 {
 	i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
 	i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+	sprintf(i->rev_type, "1.%d", i->rev);
 	switch (i->partnum) {
 	case SOC_ID_AMAZON_SE:
 		i->name = SOC_AMAZON_SE;
@@ -37,3 +39,10 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
 		break;
 	}
 }
+
+void __init ltq_soc_setup(void)
+{
+	ltq_register_ase_asc();
+	ltq_register_gpio();
+	ltq_register_wdt();
+}
diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
index 2228133..d823a92 100644
--- a/arch/mips/lantiq/xway/prom-xway.c
+++ b/arch/mips/lantiq/xway/prom-xway.c
@@ -13,6 +13,7 @@
 
 #include <lantiq_soc.h>
 
+#include "devices.h"
 #include "../prom.h"
 
 #define SOC_DANUBE	"Danube"
@@ -28,6 +29,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
 {
 	i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
 	i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+	sprintf(i->rev_type, "1.%d", i->rev);
 	switch (i->partnum) {
 	case SOC_ID_DANUBE1:
 	case SOC_ID_DANUBE2:
@@ -52,3 +54,11 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
 		break;
 	}
 }
+
+void __init ltq_soc_setup(void)
+{
+	ltq_register_asc(0);
+	ltq_register_asc(1);
+	ltq_register_gpio();
+	ltq_register_wdt();
+}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index 8b66bd8..bd0b697 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -15,6 +15,8 @@
 
 #include <lantiq_soc.h>
 
+#include "../devices.h"
+
 #define ltq_rcu_w32(x, y)	ltq_w32((x), ltq_rcu_membase + (y))
 #define ltq_rcu_r32(x)		ltq_r32(ltq_rcu_membase + (x))
 
@@ -25,12 +27,8 @@
 #define LTQ_RCU_RST_STAT	0x0014
 #define LTQ_RCU_STAT_SHIFT	26
 
-static struct resource ltq_rcu_resource = {
-	.name   = "rcu",
-	.start  = LTQ_RCU_BASE_ADDR,
-	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
-	.flags  = IORESOURCE_MEM,
-};
+static struct resource ltq_rcu_resource =
+	MEM_RES("rcu", LTQ_RCU_BASE_ADDR, LTQ_RCU_SIZE);
 
 /* remapped base addr of the reset control unit */
 static void __iomem *ltq_rcu_membase;
@@ -45,7 +43,6 @@ EXPORT_SYMBOL_GPL(ltq_reset_cause);
 
 static void ltq_machine_restart(char *command)
 {
-	pr_notice("System restart\n");
 	local_irq_disable();
 	ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
 	unreachable();
@@ -53,31 +50,20 @@ static void ltq_machine_restart(char *command)
 
 static void ltq_machine_halt(void)
 {
-	pr_notice("System halted.\n");
 	local_irq_disable();
 	unreachable();
 }
 
 static void ltq_machine_power_off(void)
 {
-	pr_notice("Please turn off the power now.\n");
 	local_irq_disable();
 	unreachable();
 }
 
 static int __init mips_reboot_setup(void)
 {
-	/* insert and request the memory region */
-	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
-		panic("Failed to insert rcu memory");
-
-	if (request_mem_region(ltq_rcu_resource.start,
-			resource_size(&ltq_rcu_resource), "rcu") < 0)
-		panic("Failed to request rcu memory");
-
 	/* remap rcu register range */
-	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
-				resource_size(&ltq_rcu_resource));
+	ltq_rcu_membase = ltq_remap_resource(&ltq_rcu_resource);
 	if (!ltq_rcu_membase)
 		panic("Failed to remap rcu memory");
 
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
deleted file mode 100644
index f6f3267..0000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_ase_asc();
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
deleted file mode 100644
index c292f64..0000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  This program is free software; you can redistribute it and/or modify it
- *  under the terms of the GNU General Public License version 2 as published
- *  by the Free Software Foundation.
- *
- *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
- */
-
-#include <lantiq_soc.h>
-
-#include "../prom.h"
-#include "devices.h"
-
-void __init ltq_soc_setup(void)
-{
-	ltq_register_asc(0);
-	ltq_register_asc(1);
-	ltq_register_gpio();
-	ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
new file mode 100644
index 0000000..38c122f
--- /dev/null
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -0,0 +1,78 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/ioport.h>
+#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
+#include "../devices.h"
+
+/* clock control register */
+#define LTQ_CGU_IFCCR	0x0018
+
+/* the enable / disable registers */
+#define LTQ_PMU_PWDCR	0x1C
+#define LTQ_PMU_PWDSR	0x20
+
+#define ltq_pmu_w32(x, y)	ltq_w32((x), ltq_pmu_membase + (y))
+#define ltq_pmu_r32(x)		ltq_r32(ltq_pmu_membase + (x))
+
+static struct resource ltq_cgu_resource =
+	MEM_RES("cgu", LTQ_CGU_BASE_ADDR, LTQ_CGU_SIZE);
+
+static struct resource ltq_pmu_resource =
+	MEM_RES("pmu", LTQ_PMU_BASE_ADDR, LTQ_PMU_SIZE);
+
+static struct resource ltq_ebu_resource =
+	MEM_RES("ebu", LTQ_EBU_BASE_ADDR, LTQ_EBU_SIZE);
+
+void __iomem *ltq_cgu_membase;
+void __iomem *ltq_ebu_membase;
+static void __iomem *ltq_pmu_membase;
+
+void ltq_cgu_enable(unsigned int clk)
+{
+	ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk, LTQ_CGU_IFCCR);
+}
+
+void ltq_pmu_enable(unsigned int module)
+{
+	int err = 1000000;
+
+	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
+	do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
+
+	if (!err)
+		panic("activating PMU module failed!");
+}
+EXPORT_SYMBOL(ltq_pmu_enable);
+
+void ltq_pmu_disable(unsigned int module)
+{
+	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
+}
+EXPORT_SYMBOL(ltq_pmu_disable);
+
+void __init ltq_soc_init(void)
+{
+	ltq_pmu_membase = ltq_remap_resource(&ltq_pmu_resource);
+	if (!ltq_pmu_membase)
+		panic("Failed to remap pmu memory");
+
+	ltq_cgu_membase = ltq_remap_resource(&ltq_cgu_resource);
+	if (!ltq_cgu_membase)
+		panic("Failed to remap cgu memory");
+
+	ltq_ebu_membase = ltq_remap_resource(&ltq_ebu_resource);
+	if (!ltq_ebu_membase)
+		panic("Failed to remap ebu memory");
+
+	/* make sure to unprotect the memory region where flash is located */
+	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 4f9eb0b..c97087d 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -498,7 +498,7 @@ static inline void local_r4k_flush_cache_page(void *args)
 		if (map_coherent)
 			vaddr = kmap_coherent(page, addr);
 		else
-			vaddr = kmap_atomic(page, KM_USER0);
+			vaddr = kmap_atomic(page);
 		addr = (unsigned long)vaddr;
 	}
 
@@ -521,7 +521,7 @@ static inline void local_r4k_flush_cache_page(void *args)
 		if (map_coherent)
 			kunmap_coherent();
 		else
-			kunmap_atomic(vaddr, KM_USER0);
+			kunmap_atomic(vaddr);
 	}
 }
 
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 937cf33..69ebd58 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -42,6 +42,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
 	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);
 
 #if 0
 	printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
@@ -91,6 +93,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+retry:
 	down_read(&mm->mmap_sem);
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -144,7 +147,11 @@ good_area:
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+	fault = handle_mm_fault(mm, vma, address, flags);
+
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return;
+
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 	if (unlikely(fault & VM_FAULT_ERROR)) {
 		if (fault & VM_FAULT_OOM)
@@ -153,12 +160,27 @@ good_area:
 			goto do_sigbus;
 		BUG();
 	}
-	if (fault & VM_FAULT_MAJOR) {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
-		tsk->maj_flt++;
-	} else {
-		perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
-		tsk->min_flt++;
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR) {
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
+						  regs, address);
+			tsk->maj_flt++;
+		} else {
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1,
+						  regs, address);
+			tsk->min_flt++;
+		}
+		if (fault & VM_FAULT_RETRY) {
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+			/*
+			 * No need to up_read(&mm->mmap_sem) as we would
+			 * have already released it in __lock_page_or_retry
+			 * in mm/filemap.c.
+			 */
+
+			goto retry;
+		}
 	}
 
 	up_read(&mm->mmap_sem);
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 3634c7e..aff5705 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(kunmap);
  * kmaps are appropriate for short, tight code paths only.
  */
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	unsigned long vaddr;
 	int idx, type;
@@ -62,7 +62,7 @@ void *__kmap_atomic(struct page *page)
 
 	return (void*) vaddr;
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 3b3ffd4..1a85ba9 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -207,21 +207,21 @@ void copy_user_highpage(struct page *to, struct page *from,
 {
 	void *vfrom, *vto;
 
-	vto = kmap_atomic(to, KM_USER1);
+	vto = kmap_atomic(to);
 	if (cpu_has_dc_aliases &&
 	    page_mapped(from) && !Page_dcache_dirty(from)) {
 		vfrom = kmap_coherent(from, vaddr);
 		copy_page(vto, vfrom);
 		kunmap_coherent();
 	} else {
-		vfrom = kmap_atomic(from, KM_USER0);
+		vfrom = kmap_atomic(from);
 		copy_page(vto, vfrom);
-		kunmap_atomic(vfrom, KM_USER0);
+		kunmap_atomic(vfrom);
 	}
 	if ((!cpu_has_ic_fills_f_dc) ||
 	    pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
 		flush_data_cache_page((unsigned long)vto);
-	kunmap_atomic(vto, KM_USER1);
+	kunmap_atomic(vto);
 	/* Make sure this page is cleared on other CPU's too before using it */
 	smp_wmb();
 }
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index be1e1af..3bf42c8 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -69,29 +69,28 @@
 #define ltq_pci_cfg_r32(x)	ltq_r32(ltq_pci_mapped_cfg + (x))
 
 struct ltq_pci_gpio_map {
-	int pin;
-	int alt0;
-	int alt1;
-	int dir;
+	unsigned int pin;
+	unsigned int mux;
+	unsigned char dir;
 	char *name;
 };
 
 /* the pci core can make use of the following gpios */
 static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
-	{ 0, 1, 0, 0, "pci-exin0" },
-	{ 1, 1, 0, 0, "pci-exin1" },
-	{ 2, 1, 0, 0, "pci-exin2" },
-	{ 39, 1, 0, 0, "pci-exin3" },
-	{ 10, 1, 0, 0, "pci-exin4" },
-	{ 9, 1, 0, 0, "pci-exin5" },
-	{ 30, 1, 0, 1, "pci-gnt1" },
-	{ 23, 1, 0, 1, "pci-gnt2" },
-	{ 19, 1, 0, 1, "pci-gnt3" },
-	{ 38, 1, 0, 1, "pci-gnt4" },
-	{ 29, 1, 0, 0, "pci-req1" },
-	{ 31, 1, 0, 0, "pci-req2" },
-	{ 3, 1, 0, 0, "pci-req3" },
-	{ 37, 1, 0, 0, "pci-req4" },
+	{ .pin = 0, .mux = 2, .dir = 0, .name = "pci-exin0" },
+	{ .pin = 1, .mux = 2, .dir = 0, .name = "pci-exin1" },
+	{ .pin = 2, .mux = 2, .dir = 0, .name = "pci-exin2" },
+	{ .pin = 39, .mux = 2, .dir = 0, .name = "pci-exin3" },
+	{ .pin = 10, .mux = 2, .dir = 0, .name = "pci-exin4" },
+	{ .pin = 9, .mux = 2, .dir = 0, .name = "pci-exin5" },
+	{ .pin = 30, .mux = 2, .dir = 1, .name = "pci-gnt1" },
+	{ .pin = 23, .mux = 2, .dir = 1, .name = "pci-gnt2" },
+	{ .pin = 19, .mux = 2, .dir = 1, .name = "pci-gnt3" },
+	{ .pin = 38, .mux = 2, .dir = 1, .name = "pci-gnt4" },
+	{ .pin = 29, .mux = 2, .dir = 0, .name = "pci-req1" },
+	{ .pin = 31, .mux = 2, .dir = 0, .name = "pci-req2" },
+	{ .pin = 3, .mux = 2, .dir = 0, .name = "pci-req3" },
+	{ .pin = 37, .mux = 2, .dir = 0, .name = "pci-req4" },
 };
 
 __iomem void *ltq_pci_mapped_cfg;
@@ -157,13 +156,12 @@ static void ltq_pci_setup_gpio(int gpio)
 	for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
 		if (gpio & (1 << i)) {
 			ltq_gpio_request(ltq_pci_gpio_map[i].pin,
-				ltq_pci_gpio_map[i].alt0,
-				ltq_pci_gpio_map[i].alt1,
+				ltq_pci_gpio_map[i].mux,
 				ltq_pci_gpio_map[i].dir,
 				ltq_pci_gpio_map[i].name);
 		}
 	}
-	ltq_gpio_request(21, 0, 0, 1, "pci-reset");
+	ltq_gpio_request(21, 0, 1, "pci-reset");
 	ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
 }
 
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index aec2b11..1552150 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -279,7 +279,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	/* Propagate hose info into the subordinate devices.  */
 
-	struct list_head *ln;
 	struct pci_dev *dev = bus->self;
 
 	if (pci_probe_only && dev &&
@@ -288,9 +287,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 		pcibios_fixup_device_resources(dev, bus);
 	}
 
-	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-		dev = pci_dev_b(ln);
-
+	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 			pcibios_fixup_device_resources(dev, bus);
 	}
diff --git a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c
index 86b98e9..62ead66 100644
--- a/arch/mips/pmc-sierra/yosemite/ht-irq.c
+++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c
@@ -35,16 +35,6 @@
  */
 void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus)
 {
-	struct pci_bus *current_bus = bus;
-	struct pci_dev *devices;
-	struct list_head *devices_link;
-
-	list_for_each(devices_link, &(current_bus->devices)) {
-		devices = pci_dev_b(devices_link);
-		if (devices == NULL)
-			continue;
-	}
-
 	/*
 	 * PLX and SPKT related changes go here
 	 */
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c
index 8e93b21..4642f56 100644
--- a/arch/mips/txx9/generic/7segled.c
+++ b/arch/mips/txx9/generic/7segled.c
@@ -102,7 +102,7 @@ static int __init tx_7segled_init_sysfs(void)
 			break;
 		}
 		dev->id = i;
-		dev->dev = &tx_7segled_subsys;
+		dev->bus = &tx_7segled_subsys;
 		error = device_register(dev);
 		if (!error) {
 			device_create_file(dev, &dev_attr_ascii);
diff --git a/arch/mn10300/include/asm/highmem.h b/arch/mn10300/include/asm/highmem.h
index bfe2d88..7c137cd 100644
--- a/arch/mn10300/include/asm/highmem.h
+++ b/arch/mn10300/include/asm/highmem.h
@@ -70,7 +70,7 @@ static inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-static inline unsigned long __kmap_atomic(struct page *page)
+static inline unsigned long kmap_atomic(struct page *page)
 {
 	unsigned long vaddr;
 	int idx, type;
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index da601dd..9f21ab0 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -140,7 +140,7 @@ static inline void *kmap(struct page *page)
 
 #define kunmap(page)			kunmap_parisc(page_address(page))
 
-static inline void *__kmap_atomic(struct page *page)
+static inline void *kmap_atomic(struct page *page)
 {
 	pagefault_disable();
 	return page_address(page);
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 2388bdb..49df148 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -8,6 +8,29 @@
 #include <asm/atomic.h>
 #include <asm/errno.h>
 
+/* The following has to match the LWS code in syscall.S.  We have
+   sixteen four-word locks. */
+
+static inline void
+_futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags)
+{
+	extern u32 lws_lock_start[];
+	long index = ((long)uaddr & 0xf0) >> 2;
+	arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
+	local_irq_save(*flags);
+	arch_spin_lock(s);
+}
+
+static inline void
+_futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags)
+{
+	extern u32 lws_lock_start[];
+	long index = ((long)uaddr & 0xf0) >> 2;
+	arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index];
+	arch_spin_unlock(s);
+	local_irq_restore(*flags);
+}
+
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
@@ -26,7 +49,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 
 	pagefault_disable();
 
-	_atomic_spin_lock_irqsave(uaddr, flags);
+	_futex_spin_lock_irqsave(uaddr, &flags);
 
 	switch (op) {
 	case FUTEX_OP_SET:
@@ -71,7 +94,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 		ret = -ENOSYS;
 	}
 
-	_atomic_spin_unlock_irqrestore(uaddr, flags);
+	_futex_spin_unlock_irqrestore(uaddr, &flags);
 
 	pagefault_enable();
 
@@ -113,7 +136,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 	 * address. This should scale to a couple of CPUs.
 	 */
 
-	_atomic_spin_lock_irqsave(uaddr, flags);
+	_futex_spin_lock_irqsave(uaddr, &flags);
 
 	ret = get_user(val, uaddr);
 
@@ -122,7 +145,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 
 	*uval = val;
 
-	_atomic_spin_unlock_irqrestore(uaddr, flags);
+	_futex_spin_unlock_irqrestore(uaddr, &flags);
 
 	return ret;
 }
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 1919634..48ab0bb 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -152,6 +152,7 @@ config COMPAT
 	bool
 	default y if PPC64
 	select COMPAT_BINFMT_ELF
+	select ARCH_WANT_OLD_COMPAT_IPC
 
 config SYSVIPC_COMPAT
 	bool
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h
index dbc2640..caaf6e0 100644
--- a/arch/powerpc/include/asm/highmem.h
+++ b/arch/powerpc/include/asm/highmem.h
@@ -79,7 +79,7 @@ static inline void kunmap(struct page *page)
 	kunmap_high(page);
 }
 
-static inline void *__kmap_atomic(struct page *page)
+static inline void *kmap_atomic(struct page *page)
 {
 	return kmap_atomic_prot(page, kmap_prot);
 }
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index e2cfb9e..220fcdf 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -227,14 +227,14 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
 	hpage_offset /= 4;
 
 	get_page(hpage);
-	page = kmap_atomic(hpage, KM_USER0);
+	page = kmap_atomic(hpage);
 
 	/* patch dcbz into reserved instruction, so we trap */
 	for (i=hpage_offset; i < hpage_offset + (HW_PAGE_SIZE / 4); i++)
 		if ((page[i] & 0xff0007ff) == INS_DCBZ)
 			page[i] &= 0xfffffff7;
 
-	kunmap_atomic(page, KM_USER0);
+	kunmap_atomic(page);
 	put_page(hpage);
 }
 
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
index 329be36..6747eec 100644
--- a/arch/powerpc/mm/dma-noncoherent.c
+++ b/arch/powerpc/mm/dma-noncoherent.c
@@ -365,12 +365,11 @@ static inline void __dma_sync_page_highmem(struct page *page,
 	local_irq_save(flags);
 
 	do {
-		start = (unsigned long)kmap_atomic(page + seg_nr,
-				KM_PPC_SYNC_PAGE) + seg_offset;
+		start = (unsigned long)kmap_atomic(page + seg_nr) + seg_offset;
 
 		/* Sync this buffer segment */
 		__dma_sync((void *)start, seg_size, direction);
-		kunmap_atomic((void *)start, KM_PPC_SYNC_PAGE);
+		kunmap_atomic((void *)start);
 		seg_nr++;
 
 		/* Calculate next buffer segment size */
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index a8b3cc7..57c7465 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -910,9 +910,9 @@ void flush_dcache_icache_hugepage(struct page *page)
 		if (!PageHighMem(page)) {
 			__flush_dcache_icache(page_address(page+i));
 		} else {
-			start = kmap_atomic(page+i, KM_PPC_SYNC_ICACHE);
+			start = kmap_atomic(page+i);
 			__flush_dcache_icache(start);
-			kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+			kunmap_atomic(start);
 		}
 	}
 }
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index d974b79..baaafde 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -458,9 +458,9 @@ void flush_dcache_icache_page(struct page *page)
 #endif
 #ifdef CONFIG_BOOKE
 	{
-		void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
+		void *start = kmap_atomic(page);
 		__flush_dcache_icache(start);
-		kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
+		kunmap_atomic(start);
 	}
 #elif defined(CONFIG_8xx) || defined(CONFIG_PPC64)
 	/* On 8xx there is no need to kmap since highmem is not supported */
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d172758..47bc8a6 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -218,6 +218,7 @@ config COMPAT
 	prompt "Kernel support for 31 bit emulation"
 	depends on 64BIT
 	select COMPAT_BINFMT_ELF
+	select ARCH_WANT_OLD_COMPAT_IPC
 	help
 	  Select this option if you want to enable your system kernel to
 	  handle system-calls from ELF binaries for 31 bit ESA.  This option
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index e9f3533..0ad2f1e 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -88,7 +88,6 @@ KBUILD_CFLAGS	+= -pipe -fno-strength-reduce -Wno-sign-compare
 KBUILD_AFLAGS	+= $(aflags-y)
 
 OBJCOPYFLAGS	:= -O binary
-LDFLAGS_vmlinux := -e start
 
 head-y		:= arch/s390/kernel/head.o
 head-y		+= arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h
index cf4e47b..3f30dac 100644
--- a/arch/s390/include/asm/kexec.h
+++ b/arch/s390/include/asm/kexec.h
@@ -42,6 +42,24 @@
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_S390
 
+/*
+ * Size for s390x ELF notes per CPU
+ *
+ * Seven notes plus zero note at the end: prstatus, fpregset, timer,
+ * tod_cmp, tod_reg, control regs, and prefix
+ */
+#define KEXEC_NOTE_BYTES \
+	(ALIGN(sizeof(struct elf_note), 4) * 8 + \
+	 ALIGN(sizeof("CORE"), 4) * 7 + \
+	 ALIGN(sizeof(struct elf_prstatus), 4) + \
+	 ALIGN(sizeof(elf_fpregset_t), 4) + \
+	 ALIGN(sizeof(u64), 4) + \
+	 ALIGN(sizeof(u64), 4) + \
+	 ALIGN(sizeof(u32), 4) + \
+	 ALIGN(sizeof(u64) * 16, 4) + \
+	 ALIGN(sizeof(u32), 4) \
+	)
+
 /* Provide a dummy definition to avoid build failures. */
 static inline void crash_setup_regs(struct pt_regs *newregs,
 					struct pt_regs *oldregs) { }
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index e4c79eb..21109c6 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -9,12 +9,12 @@
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
 OUTPUT_ARCH(s390)
-ENTRY(_start)
+ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
-ENTRY(_start)
+ENTRY(startup)
 jiffies = jiffies_64;
 #endif
 
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S
index 577abba..83bb960 100644
--- a/arch/score/kernel/entry.S
+++ b/arch/score/kernel/entry.S
@@ -408,7 +408,7 @@ ENTRY(handle_sys)
 	sw	r9, [r0, PT_EPC]
 
 	cmpi.c	r27, __NR_syscalls 	# check syscall number
-	bgtu	illegal_syscall
+	bgeu	illegal_syscall
 
 	slli	r8, r27, 2		# get syscall routine
 	la	r11, sys_call_table
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 92eb986..112fea1 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -244,7 +244,7 @@ static void sh4_flush_cache_page(void *args)
 		if (map_coherent)
 			vaddr = kmap_coherent(page, address);
 		else
-			vaddr = kmap_atomic(page, KM_USER0);
+			vaddr = kmap_atomic(page);
 
 		address = (unsigned long)vaddr;
 	}
@@ -259,7 +259,7 @@ static void sh4_flush_cache_page(void *args)
 		if (map_coherent)
 			kunmap_coherent(vaddr);
 		else
-			kunmap_atomic(vaddr, KM_USER0);
+			kunmap_atomic(vaddr);
 	}
 }
 
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index 5a580ea..616966a 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -95,7 +95,7 @@ void copy_user_highpage(struct page *to, struct page *from,
 {
 	void *vfrom, *vto;
 
-	vto = kmap_atomic(to, KM_USER1);
+	vto = kmap_atomic(to);
 
 	if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
 	    test_bit(PG_dcache_clean, &from->flags)) {
@@ -103,16 +103,16 @@ void copy_user_highpage(struct page *to, struct page *from,
 		copy_page(vto, vfrom);
 		kunmap_coherent(vfrom);
 	} else {
-		vfrom = kmap_atomic(from, KM_USER0);
+		vfrom = kmap_atomic(from);
 		copy_page(vto, vfrom);
-		kunmap_atomic(vfrom, KM_USER0);
+		kunmap_atomic(vfrom);
 	}
 
 	if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK) ||
 	    (vma->vm_flags & VM_EXEC))
 		__flush_purge_region(vto, PAGE_SIZE);
 
-	kunmap_atomic(vto, KM_USER1);
+	kunmap_atomic(vto);
 	/* Make sure this page is cleared on other CPU's too before using it */
 	smp_wmb();
 }
@@ -120,14 +120,14 @@ EXPORT_SYMBOL(copy_user_highpage);
 
 void clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *kaddr = kmap_atomic(page, KM_USER0);
+	void *kaddr = kmap_atomic(page);
 
 	clear_page(kaddr);
 
 	if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
 		__flush_purge_region(kaddr, PAGE_SIZE);
 
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 EXPORT_SYMBOL(clear_user_highpage);
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9665799..55319c5 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -575,6 +575,7 @@ config COMPAT
 	depends on SPARC64
 	default y
 	select COMPAT_BINFMT_ELF
+	select ARCH_WANT_OLD_COMPAT_IPC
 
 config SYSVIPC_COMPAT
 	bool
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
index 3d7afbb..3b6e00d 100644
--- a/arch/sparc/include/asm/highmem.h
+++ b/arch/sparc/include/asm/highmem.h
@@ -70,7 +70,7 @@ static inline void kunmap(struct page *page)
 	kunmap_high(page);
 }
 
-extern void *__kmap_atomic(struct page *page);
+extern void *kmap_atomic(struct page *page);
 extern void __kunmap_atomic(void *kvaddr);
 extern struct page *kmap_atomic_to_page(void *vaddr);
 
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 422c16d..e611651 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -399,6 +399,9 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
 	timers_global = (void __iomem *)
 		(unsigned long) addr[num_cpu_timers];
 
+	/* Every per-cpu timer works in timer mode */
+	sbus_writel(0x00000000, &timers_global->timer_config);
+
 	sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
 
 	master_l10_counter = &timers_global->l10_count;
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
index 77140a0..055c66c 100644
--- a/arch/sparc/mm/highmem.c
+++ b/arch/sparc/mm/highmem.c
@@ -30,7 +30,7 @@
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	unsigned long vaddr;
 	long idx, type;
@@ -64,7 +64,7 @@ void *__kmap_atomic(struct page *page)
 
 	return (void*) vaddr;
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index bf95f55..4b4b289 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -242,17 +242,6 @@ long compat_sys_fallocate(int fd, int mode,
 long compat_sys_sched_rr_get_interval(compat_pid_t pid,
 				      struct compat_timespec __user *interval);
 
-/* Versions of compat functions that differ from generic Linux. */
-struct compat_msgbuf;
-long tile_compat_sys_msgsnd(int msqid,
-			    struct compat_msgbuf __user *msgp,
-			    size_t msgsz, int msgflg);
-long tile_compat_sys_msgrcv(int msqid,
-			    struct compat_msgbuf __user *msgp,
-			    size_t msgsz, long msgtyp, int msgflg);
-long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid,
-			    compat_long_t addr, compat_long_t data);
-
 /* Tilera Linux syscalls that don't have "compat" versions. */
 #define compat_sys_flush_cache sys_flush_cache
 
diff --git a/arch/tile/include/asm/highmem.h b/arch/tile/include/asm/highmem.h
index b2a6c5d..fc8429a 100644
--- a/arch/tile/include/asm/highmem.h
+++ b/arch/tile/include/asm/highmem.h
@@ -59,7 +59,7 @@ void *kmap_fix_kpte(struct page *page, int finished);
 /* This macro is used only in map_new_virtual() to map "page". */
 #define kmap_prot page_to_kpgprot(page)
 
-void *__kmap_atomic(struct page *page);
+void *kmap_atomic(struct page *page);
 void __kunmap_atomic(void *kvaddr);
 void *kmap_atomic_pfn(unsigned long pfn);
 void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c
index bf5e9d7..d67459b 100644
--- a/arch/tile/kernel/compat.c
+++ b/arch/tile/kernel/compat.c
@@ -16,7 +16,6 @@
 #define __SYSCALL_COMPAT
 
 #include <linux/compat.h>
-#include <linux/msg.h>
 #include <linux/syscalls.h>
 #include <linux/kdev_t.h>
 #include <linux/fs.h>
@@ -95,52 +94,10 @@ long compat_sys_sched_rr_get_interval(compat_pid_t pid,
 	return ret;
 }
 
-/*
- * The usual compat_sys_msgsnd() and _msgrcv() seem to be assuming
- * some different calling convention than our normal 32-bit tile code.
- */
-
-/* Already defined in ipc/compat.c, but we need it here. */
-struct compat_msgbuf {
-	compat_long_t mtype;
-	char mtext[1];
-};
-
-long tile_compat_sys_msgsnd(int msqid,
-			    struct compat_msgbuf __user *msgp,
-			    size_t msgsz, int msgflg)
-{
-	compat_long_t mtype;
-
-	if (get_user(mtype, &msgp->mtype))
-		return -EFAULT;
-	return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
-}
-
-long tile_compat_sys_msgrcv(int msqid,
-			    struct compat_msgbuf __user *msgp,
-			    size_t msgsz, long msgtyp, int msgflg)
-{
-	long err, mtype;
-
-	err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
-	if (err < 0)
-		goto out;
-
-	if (put_user(mtype, &msgp->mtype))
-		err = -EFAULT;
- out:
-	return err;
-}
-
 /* Provide the compat syscall number to call mapping. */
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
 
-/* The generic versions of these don't work for Tile. */
-#define compat_sys_msgrcv tile_compat_sys_msgrcv
-#define compat_sys_msgsnd tile_compat_sys_msgsnd
-
 /* See comments in sys.c */
 #define compat_sys_fadvise64_64 sys32_fadvise64_64
 #define compat_sys_readahead sys32_readahead
diff --git a/arch/tile/mm/highmem.c b/arch/tile/mm/highmem.c
index 31dbbd9..ef8e5a6 100644
--- a/arch/tile/mm/highmem.c
+++ b/arch/tile/mm/highmem.c
@@ -224,12 +224,12 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	/* PAGE_NONE is a magic value that tells us to check immutability. */
 	return kmap_atomic_prot(page, PAGE_NONE);
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index 9fefd92..cd7df79 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -69,7 +69,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
 		return -1;
 
 	page = pte_page(*pte);
-	addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
+	addr = (unsigned long) kmap_atomic(page) +
 		(addr & ~PAGE_MASK);
 
 	current->thread.fault_catcher = &buf;
@@ -82,7 +82,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write,
 
 	current->thread.fault_catcher = NULL;
 
-	kunmap_atomic((void *)addr, KM_UML_USERCOPY);
+	kunmap_atomic((void *)addr);
 
 	return n;
 }
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 864cc6e..f50561b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -84,7 +84,7 @@ config X86
 	select GENERIC_IOMAP
 
 config INSTRUCTION_DECODER
-	def_bool (KPROBES || PERF_EVENTS)
+	def_bool (KPROBES || PERF_EVENTS || UPROBES)
 
 config OUTPUT_FORMAT
 	string
@@ -240,6 +240,9 @@ config ARCH_CPU_PROBE_RELEASE
 	def_bool y
 	depends on HOTPLUG_CPU
 
+config ARCH_SUPPORTS_UPROBES
+	def_bool y
+
 source "init/Kconfig"
 source "kernel/Kconfig.freezer"
 
@@ -559,6 +562,37 @@ config SCHED_OMIT_FRAME_POINTER
 
 	  If in doubt, say "Y".
 
+config KVMTOOL_TEST_ENABLE
+	bool "Enable options to create a bootable tools/kvm/ kernel"
+	select NET
+	select NETDEVICES
+	select PCI
+	select BLOCK
+	select BLK_DEV
+	select NETWORK_FILESYSTEMS
+	select INET
+	select EXPERIMENTAL
+	select SERIAL_8250
+	select SERIAL_8250_CONSOLE
+	select IP_PNP
+	select IP_PNP_DHCP
+	select BINFMT_ELF
+	select PCI_MSI
+	select HAVE_ARCH_KGDB
+	select DEBUG_KERNEL
+	select KGDB
+	select KGDB_SERIAL_CONSOLE
+	select VIRTUALIZATION
+	select VIRTIO
+	select VIRTIO_RING
+	select VIRTIO_PCI
+	select VIRTIO_BLK
+	select VIRTIO_CONSOLE
+	select VIRTIO_NET
+	select 9P_FS
+	select NET_9P
+	select NET_9P_VIRTIO
+
 menuconfig PARAVIRT_GUEST
 	bool "Paravirtualized guest support"
 	---help---
@@ -2134,6 +2168,13 @@ config ALIX
 
 	  Note: You have to set alix.force=1 for boards with Award BIOS.
 
+config GEOS
+	bool "Traverse Technologies GEOS System Support (LEDS, GPIO, etc)"
+	select GPIOLIB
+	depends on DMI
+	---help---
+	  This option enables system support for the Traverse Technologies GEOS.
+
 endif # X86_32
 
 config AMD_NB
@@ -2179,6 +2220,7 @@ config IA32_AOUT
 config COMPAT
 	def_bool y
 	depends on IA32_EMULATION
+	select ARCH_WANT_OLD_COMPAT_IPC
 
 config COMPAT_FOR_U64_ALIGNMENT
 	def_bool COMPAT
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 545d0ce..152232d 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -1107,12 +1107,12 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
 		one_entry_in_sg = 1;
 		scatterwalk_start(&src_sg_walk, req->src);
 		scatterwalk_start(&assoc_sg_walk, req->assoc);
-		src = scatterwalk_map(&src_sg_walk, 0);
-		assoc = scatterwalk_map(&assoc_sg_walk, 0);
+		src = scatterwalk_map(&src_sg_walk);
+		assoc = scatterwalk_map(&assoc_sg_walk);
 		dst = src;
 		if (unlikely(req->src != req->dst)) {
 			scatterwalk_start(&dst_sg_walk, req->dst);
-			dst = scatterwalk_map(&dst_sg_walk, 0);
+			dst = scatterwalk_map(&dst_sg_walk);
 		}
 
 	} else {
@@ -1136,11 +1136,11 @@ static int __driver_rfc4106_encrypt(struct aead_request *req)
 	 * back to the packet. */
 	if (one_entry_in_sg) {
 		if (unlikely(req->src != req->dst)) {
-			scatterwalk_unmap(dst, 0);
+			scatterwalk_unmap(dst);
 			scatterwalk_done(&dst_sg_walk, 0, 0);
 		}
-		scatterwalk_unmap(src, 0);
-		scatterwalk_unmap(assoc, 0);
+		scatterwalk_unmap(src);
+		scatterwalk_unmap(assoc);
 		scatterwalk_done(&src_sg_walk, 0, 0);
 		scatterwalk_done(&assoc_sg_walk, 0, 0);
 	} else {
@@ -1189,12 +1189,12 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
 		one_entry_in_sg = 1;
 		scatterwalk_start(&src_sg_walk, req->src);
 		scatterwalk_start(&assoc_sg_walk, req->assoc);
-		src = scatterwalk_map(&src_sg_walk, 0);
-		assoc = scatterwalk_map(&assoc_sg_walk, 0);
+		src = scatterwalk_map(&src_sg_walk);
+		assoc = scatterwalk_map(&assoc_sg_walk);
 		dst = src;
 		if (unlikely(req->src != req->dst)) {
 			scatterwalk_start(&dst_sg_walk, req->dst);
-			dst = scatterwalk_map(&dst_sg_walk, 0);
+			dst = scatterwalk_map(&dst_sg_walk);
 		}
 
 	} else {
@@ -1219,11 +1219,11 @@ static int __driver_rfc4106_decrypt(struct aead_request *req)
 
 	if (one_entry_in_sg) {
 		if (unlikely(req->src != req->dst)) {
-			scatterwalk_unmap(dst, 0);
+			scatterwalk_unmap(dst);
 			scatterwalk_done(&dst_sg_walk, 0, 0);
 		}
-		scatterwalk_unmap(src, 0);
-		scatterwalk_unmap(assoc, 0);
+		scatterwalk_unmap(src);
+		scatterwalk_unmap(assoc);
 		scatterwalk_done(&src_sg_walk, 0, 0);
 		scatterwalk_done(&assoc_sg_walk, 0, 0);
 	} else {
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c
index b05aa16..2970110 100644
--- a/arch/x86/crypto/blowfish_glue.c
+++ b/arch/x86/crypto/blowfish_glue.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include <asm/processor.h>
 #include <crypto/blowfish.h>
 #include <linux/crypto.h>
 #include <linux/init.h>
@@ -446,10 +447,39 @@ static struct crypto_alg blk_ctr_alg = {
 	},
 };
 
+static bool is_blacklisted_cpu(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return false;
+
+	if (boot_cpu_data.x86 == 0x0f) {
+		/*
+		 * On Pentium 4, blowfish-x86_64 is slower than generic C
+		 * implementation because use of 64bit rotates (which are really
+		 * slow on P4). Therefore blacklist P4s.
+		 */
+		return true;
+	}
+
+	return false;
+}
+
+static int force;
+module_param(force, int, 0);
+MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
+
 static int __init init(void)
 {
 	int err;
 
+	if (!force && is_blacklisted_cpu()) {
+		printk(KERN_INFO
+			"blowfish-x86_64: performance on this CPU "
+			"would be suboptimal: disabling "
+			"blowfish-x86_64.\n");
+		return -ENODEV;
+	}
+
 	err = crypto_register_alg(&bf_alg);
 	if (err)
 		goto bf_err;
diff --git a/arch/x86/crypto/serpent-sse2-i586-asm_32.S b/arch/x86/crypto/serpent-sse2-i586-asm_32.S
index 4e37677..c00053d 100644
--- a/arch/x86/crypto/serpent-sse2-i586-asm_32.S
+++ b/arch/x86/crypto/serpent-sse2-i586-asm_32.S
@@ -463,23 +463,20 @@
 	pand x0,		x4; \
 	pxor x2,		x4;
 
-#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
-	movdqa x2,		t3; \
-	movdqa x0,		t1; \
-	unpcklps x3,		t3; \
+#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
 	movdqa x0,		t2; \
-	unpcklps x1,		t1; \
-	unpckhps x1,		t2; \
-	movdqa t3,		x1; \
-	unpckhps x3,		x2; \
-	movdqa t1,		x0; \
-	movhlps t1,		x1; \
-	movdqa t2,		t1; \
-	movlhps t3,		x0; \
-	movlhps x2,		t1; \
-	movhlps t2,		x2; \
-	movdqa x2,		x3; \
-	movdqa t1,		x2;
+	punpckldq x1,		x0; \
+	punpckhdq x1,		t2; \
+	movdqa x2,		t1; \
+	punpckhdq x3,		x2; \
+	punpckldq x3,		t1; \
+	movdqa x0,		x1; \
+	punpcklqdq t1,		x0; \
+	punpckhqdq t1,		x1; \
+	movdqa t2,		x3; \
+	punpcklqdq x2,		t2; \
+	punpckhqdq x2,		x3; \
+	movdqa t2,		x2;
 
 #define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \
 	movdqu (0*4*4)(in),	x0; \
diff --git a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
index 7f24a15..3ee1ff0 100644
--- a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
+++ b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S
@@ -585,23 +585,20 @@
 	get_key(i, 1, RK1); \
 	SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \
 
-#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \
-	movdqa x2,		t3; \
-	movdqa x0,		t1; \
-	unpcklps x3,		t3; \
+#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
 	movdqa x0,		t2; \
-	unpcklps x1,		t1; \
-	unpckhps x1,		t2; \
-	movdqa t3,		x1; \
-	unpckhps x3,		x2; \
-	movdqa t1,		x0; \
-	movhlps t1,		x1; \
-	movdqa t2,		t1; \
-	movlhps t3,		x0; \
-	movlhps x2,		t1; \
-	movhlps t2,		x2; \
-	movdqa x2,		x3; \
-	movdqa t1,		x2;
+	punpckldq x1,		x0; \
+	punpckhdq x1,		t2; \
+	movdqa x2,		t1; \
+	punpckhdq x3,		x2; \
+	punpckldq x3,		t1; \
+	movdqa x0,		x1; \
+	punpcklqdq t1,		x0; \
+	punpckhqdq t1,		x1; \
+	movdqa t2,		x3; \
+	punpcklqdq x2,		t2; \
+	punpckhqdq x2,		x3; \
+	movdqa t2,		x2;
 
 #define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \
 	movdqu (0*4*4)(in),	x0; \
diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c
index 7fee8c1..0afd134 100644
--- a/arch/x86/crypto/twofish_glue_3way.c
+++ b/arch/x86/crypto/twofish_glue_3way.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include <asm/processor.h>
 #include <linux/crypto.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -637,10 +638,56 @@ static struct crypto_alg blk_xts_alg = {
 	},
 };
 
+static bool is_blacklisted_cpu(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return false;
+
+	if (boot_cpu_data.x86 == 0x06 &&
+		(boot_cpu_data.x86_model == 0x1c ||
+		 boot_cpu_data.x86_model == 0x26 ||
+		 boot_cpu_data.x86_model == 0x36)) {
+		/*
+		 * On Atom, twofish-3way is slower than original assembler
+		 * implementation. Twofish-3way trades off some performance in
+		 * storing blocks in 64bit registers to allow three blocks to
+		 * be processed parallel. Parallel operation then allows gaining
+		 * more performance than was trade off, on out-of-order CPUs.
+		 * However Atom does not benefit from this parallellism and
+		 * should be blacklisted.
+		 */
+		return true;
+	}
+
+	if (boot_cpu_data.x86 == 0x0f) {
+		/*
+		 * On Pentium 4, twofish-3way is slower than original assembler
+		 * implementation because excessive uses of 64bit rotate and
+		 * left-shifts (which are really slow on P4) needed to store and
+		 * handle 128bit block in two 64bit registers.
+		 */
+		return true;
+	}
+
+	return false;
+}
+
+static int force;
+module_param(force, int, 0);
+MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist");
+
 int __init init(void)
 {
 	int err;
 
+	if (!force && is_blacklisted_cpu()) {
+		printk(KERN_INFO
+			"twofish-x86_64-3way: performance on this CPU "
+			"would be suboptimal: disabling "
+			"twofish-x86_64-3way.\n");
+		return -ENODEV;
+	}
+
 	err = crypto_register_alg(&blk_ecb_alg);
 	if (err)
 		goto ecb_err;
diff --git a/arch/x86/include/asm/current.h b/arch/x86/include/asm/current.h
index 4d447b7..9476c04 100644
--- a/arch/x86/include/asm/current.h
+++ b/arch/x86/include/asm/current.h
@@ -11,7 +11,7 @@ DECLARE_PER_CPU(struct task_struct *, current_task);
 
 static __always_inline struct task_struct *get_current(void)
 {
-	return percpu_read_stable(current_task);
+	return this_cpu_read_stable(current_task);
 }
 
 #define current get_current()
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index e95822d..3072a2d 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -6,6 +6,8 @@
 #include <asm/mmu.h>
 
 #include <linux/smp.h>
+#include <linux/percpu.h>
+
 
 static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info)
 {
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index da0b3ca..b6e5c83 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -36,14 +36,15 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
 
 #define __ARCH_IRQ_STAT
 
-#define inc_irq_stat(member)	percpu_inc(irq_stat.member)
+#define inc_irq_stat(member)	__this_cpu_inc(irq_stat.member)
 
-#define local_softirq_pending()	percpu_read(irq_stat.__softirq_pending)
+#define local_softirq_pending()	__this_cpu_read(irq_stat.__softirq_pending)
 
 #define __ARCH_SET_SOFTIRQ_PENDING
 
-#define set_softirq_pending(x)	percpu_write(irq_stat.__softirq_pending, (x))
-#define or_softirq_pending(x)	percpu_or(irq_stat.__softirq_pending, (x))
+#define set_softirq_pending(x)	\
+		__this_cpu_write(irq_stat.__softirq_pending, (x))
+#define or_softirq_pending(x)	__this_cpu_or(irq_stat.__softirq_pending, (x))
 
 extern void ack_bad_irq(unsigned int irq);
 
diff --git a/arch/x86/include/asm/highmem.h b/arch/x86/include/asm/highmem.h
index 3bd0402..302a323 100644
--- a/arch/x86/include/asm/highmem.h
+++ b/arch/x86/include/asm/highmem.h
@@ -61,7 +61,7 @@ void *kmap(struct page *page);
 void kunmap(struct page *page);
 
 void *kmap_atomic_prot(struct page *page, pgprot_t prot);
-void *__kmap_atomic(struct page *page);
+void *kmap_atomic(struct page *page);
 void __kunmap_atomic(void *kvaddr);
 void *kmap_atomic_pfn(unsigned long pfn);
 void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
diff --git a/arch/x86/include/asm/irq_regs.h b/arch/x86/include/asm/irq_regs.h
index 7784322..15639ed 100644
--- a/arch/x86/include/asm/irq_regs.h
+++ b/arch/x86/include/asm/irq_regs.h
@@ -15,7 +15,7 @@ DECLARE_PER_CPU(struct pt_regs *, irq_regs);
 
 static inline struct pt_regs *get_irq_regs(void)
 {
-	return percpu_read(irq_regs);
+	return __this_cpu_read(irq_regs);
 }
 
 static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
@@ -23,7 +23,7 @@ static inline struct pt_regs *set_irq_regs(struct pt_regs *new_regs)
 	struct pt_regs *old_regs;
 
 	old_regs = get_irq_regs();
-	percpu_write(irq_regs, new_regs);
+	__this_cpu_write(irq_regs, new_regs);
 
 	return old_regs;
 }
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 6902152..02ca533 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -25,8 +25,8 @@ void destroy_context(struct mm_struct *mm);
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 #ifdef CONFIG_SMP
-	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
-		percpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
+	if (__this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+		__this_cpu_write(cpu_tlbstate.state, TLBSTATE_LAZY);
 #endif
 }
 
@@ -37,8 +37,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
 	if (likely(prev != next)) {
 #ifdef CONFIG_SMP
-		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
-		percpu_write(cpu_tlbstate.active_mm, next);
+		__this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK);
+		__this_cpu_write(cpu_tlbstate.active_mm, next);
 #endif
 		cpumask_set_cpu(cpu, mm_cpumask(next));
 
@@ -56,8 +56,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 	}
 #ifdef CONFIG_SMP
 	else {
-		percpu_write(cpu_tlbstate.state, TLBSTATE_OK);
-		BUG_ON(percpu_read(cpu_tlbstate.active_mm) != next);
+		__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
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index a6962d9..4e3cd38 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -127,6 +127,8 @@
 #define MSR_AMD64_IBSFETCHCTL		0xc0011030
 #define MSR_AMD64_IBSFETCHLINAD		0xc0011031
 #define MSR_AMD64_IBSFETCHPHYSAD	0xc0011032
+#define MSR_AMD64_IBSFETCH_REG_COUNT	3
+#define MSR_AMD64_IBSFETCH_REG_MASK	((1UL<<MSR_AMD64_IBSFETCH_REG_COUNT)-1)
 #define MSR_AMD64_IBSOPCTL		0xc0011033
 #define MSR_AMD64_IBSOPRIP		0xc0011034
 #define MSR_AMD64_IBSOPDATA		0xc0011035
@@ -134,8 +136,11 @@
 #define MSR_AMD64_IBSOPDATA3		0xc0011037
 #define MSR_AMD64_IBSDCLINAD		0xc0011038
 #define MSR_AMD64_IBSDCPHYSAD		0xc0011039
+#define MSR_AMD64_IBSOP_REG_COUNT	7
+#define MSR_AMD64_IBSOP_REG_MASK	((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
 #define MSR_AMD64_IBSCTL		0xc001103a
 #define MSR_AMD64_IBSBRTARGET		0xc001103b
+#define MSR_AMD64_IBS_REG_COUNT_MAX	8 /* includes MSR_AMD64_IBSBRTARGET */
 
 /* Fam 15h MSRs */
 #define MSR_F15H_PERF_CTL		0xc0010200
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 7a11910..ed3e18a 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -46,7 +46,7 @@
 
 #ifdef CONFIG_SMP
 #define __percpu_prefix		"%%"__stringify(__percpu_seg)":"
-#define __my_cpu_offset		percpu_read(this_cpu_off)
+#define __my_cpu_offset		__this_cpu_read(this_cpu_off)
 
 /*
  * Compared to the generic __my_cpu_offset version, the following
@@ -351,23 +351,15 @@ do {									\
 })
 
 /*
- * percpu_read() makes gcc load the percpu variable every time it is
- * accessed while percpu_read_stable() allows the value to be cached.
- * percpu_read_stable() is more efficient and can be used if its value
+ * this_cpu_read() makes gcc load the percpu variable every time it is
+ * accessed while this_cpu_read_stable() allows the value to be cached.
+ * this_cpu_read_stable() is more efficient and can be used if its value
  * is guaranteed to be valid across cpus.  The current users include
  * get_current() and get_thread_info() both of which are actually
  * per-thread variables implemented as per-cpu variables and thus
  * stable for the duration of the respective task.
  */
-#define percpu_read(var)		percpu_from_op("mov", var, "m" (var))
-#define percpu_read_stable(var)		percpu_from_op("mov", var, "p" (&(var)))
-#define percpu_write(var, val)		percpu_to_op("mov", var, val)
-#define percpu_add(var, val)		percpu_add_op(var, val)
-#define percpu_sub(var, val)		percpu_add_op(var, -(val))
-#define percpu_and(var, val)		percpu_to_op("and", var, val)
-#define percpu_or(var, val)		percpu_to_op("or", var, val)
-#define percpu_xor(var, val)		percpu_to_op("xor", var, val)
-#define percpu_inc(var)		percpu_unary_op("inc", var)
+#define this_cpu_read_stable(var)	percpu_from_op("mov", var, "p" (&(var)))
 
 #define __this_cpu_read_1(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
 #define __this_cpu_read_2(pcp)		percpu_from_op("mov", (pcp), "m"(pcp))
@@ -512,7 +504,11 @@ static __always_inline int x86_this_cpu_constant_test_bit(unsigned int nr,
 {
 	unsigned long __percpu *a = (unsigned long *)addr + nr / BITS_PER_LONG;
 
-	return ((1UL << (nr % BITS_PER_LONG)) & percpu_read(*a)) != 0;
+#ifdef CONFIG_X86_64
+	return ((1UL << (nr % BITS_PER_LONG)) & __this_cpu_read_8(*a)) != 0;
+#else
+	return ((1UL << (nr % BITS_PER_LONG)) & __this_cpu_read_4(*a)) != 0;
+#endif
 }
 
 static inline int x86_this_cpu_variable_test_bit(int nr,
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 096c975..5119e21 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -177,6 +177,8 @@ struct x86_pmu_capability {
 #define IBS_FETCH_MAX_CNT	0x0000FFFFULL
 
 /* IbsOpCtl bits */
+/* lower 4 bits of the current count are ignored: */
+#define IBS_OP_CUR_CNT		(0xFFFF0ULL<<32)
 #define IBS_OP_CNT_CTL		(1ULL<<19)
 #define IBS_OP_VAL		(1ULL<<18)
 #define IBS_OP_ENABLE		(1ULL<<17)
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 0434c40..e276f6b 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -188,11 +188,11 @@ extern unsigned disabled_cpus __cpuinitdata;
  * from the initial startup. We map APIC_BASE very early in page_setup(),
  * so this is correct in the x86 case.
  */
-#define raw_smp_processor_id() (percpu_read(cpu_number))
+#define raw_smp_processor_id() (this_cpu_read(cpu_number))
 extern int safe_smp_processor_id(void);
 
 #elif defined(CONFIG_X86_64_SMP)
-#define raw_smp_processor_id() (percpu_read(cpu_number))
+#define raw_smp_processor_id() (this_cpu_read(cpu_number))
 
 #define stack_smp_processor_id()					\
 ({								\
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index 1575177..e8a60c9 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -76,9 +76,9 @@ static __always_inline void boot_init_stack_canary(void)
 
 	current->stack_canary = canary;
 #ifdef CONFIG_X86_64
-	percpu_write(irq_stack_union.stack_canary, canary);
+	__this_cpu_write(irq_stack_union.stack_canary, canary);
 #else
-	percpu_write(stack_canary.canary, canary);
+	__this_cpu_write(stack_canary.canary, canary);
 #endif
 }
 
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index bc817cd..3c3467a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -85,6 +85,7 @@ struct thread_info {
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_MCE_NOTIFY		10	/* notify userspace of an MCE */
 #define TIF_USER_RETURN_NOTIFY	11	/* notify kernel of userspace return */
+#define TIF_UPROBE		12	/* breakpointed or singlestepping */
 #define TIF_NOTSC		16	/* TSC is not accessible in userland */
 #define TIF_IA32		17	/* 32bit process */
 #define TIF_FORK		18	/* ret_from_fork */
@@ -107,6 +108,7 @@ struct thread_info {
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_MCE_NOTIFY		(1 << TIF_MCE_NOTIFY)
 #define _TIF_USER_RETURN_NOTIFY	(1 << TIF_USER_RETURN_NOTIFY)
+#define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_NOTSC		(1 << TIF_NOTSC)
 #define _TIF_IA32		(1 << TIF_IA32)
 #define _TIF_FORK		(1 << TIF_FORK)
@@ -218,7 +220,7 @@ DECLARE_PER_CPU(unsigned long, kernel_stack);
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	ti = (void *)(percpu_read_stable(kernel_stack) +
+	ti = (void *)(this_cpu_read_stable(kernel_stack) +
 		      KERNEL_STACK_OFFSET - THREAD_SIZE);
 	return ti;
 }
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 169be89..e90eec0 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -156,8 +156,8 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate);
 
 static inline void reset_lazy_tlbstate(void)
 {
-	percpu_write(cpu_tlbstate.state, 0);
-	percpu_write(cpu_tlbstate.active_mm, &init_mm);
+	__this_cpu_write(cpu_tlbstate.state, 0);
+	__this_cpu_write(cpu_tlbstate.active_mm, &init_mm);
 }
 
 #endif	/* SMP */
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
new file mode 100644
index 0000000..475563b
--- /dev/null
+++ b/arch/x86/include/asm/uprobes.h
@@ -0,0 +1,59 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * Userspace Probes (UProbes) for x86
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2008-2011
+ * Authors:
+ *	Srikar Dronamraju
+ *	Jim Keniston
+ */
+
+#include <linux/notifier.h>
+
+typedef u8 uprobe_opcode_t;
+#define MAX_UINSN_BYTES 16
+#define UPROBES_XOL_SLOT_BYTES	128	/* to keep it cache aligned */
+
+#define UPROBES_BKPT_INSN 0xcc
+#define UPROBES_BKPT_INSN_SIZE 1
+
+struct uprobe_arch_info {
+	u16			fixups;
+#ifdef CONFIG_X86_64
+	unsigned long rip_rela_target_address;
+#endif
+};
+
+struct uprobe_task_arch_info {
+	unsigned long saved_trap_no;
+#ifdef CONFIG_X86_64
+	unsigned long saved_scratch_register;
+#endif
+};
+
+struct uprobe;
+
+extern int analyze_insn(struct mm_struct *mm, struct uprobe *uprobe);
+extern void set_instruction_pointer(struct pt_regs *regs, unsigned long vaddr);
+extern int pre_xol(struct uprobe *uprobe, struct pt_regs *regs);
+extern int post_xol(struct uprobe *uprobe, struct pt_regs *regs);
+extern bool xol_was_trapped(struct task_struct *tsk);
+extern int uprobe_exception_notify(struct notifier_block *self,
+				       unsigned long val, void *data);
+extern void abort_xol(struct pt_regs *regs, struct uprobe *uprobe);
+#endif	/* _ASM_UPROBES_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 5369059..8c8c365 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -100,6 +100,7 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 obj-$(CONFIG_OF)			+= devicetree.o
+obj-$(CONFIG_UPROBES)			+= uprobes.o
 
 ###
 # 64 bit specific files
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d43cad7..8fb218d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1189,7 +1189,7 @@ void __cpuinit cpu_init(void)
 	oist = &per_cpu(orig_ist, cpu);
 
 #ifdef CONFIG_NUMA
-	if (cpu != 0 && percpu_read(numa_node) == 0 &&
+	if (cpu != 0 && __this_cpu_read(numa_node) == 0 &&
 	    early_cpu_to_node(cpu) != NUMA_NO_NODE)
 		set_numa_node(early_cpu_to_node(cpu));
 #endif
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 5a11ae2..acb6189 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -562,7 +562,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
 	struct mce m;
 	int i;
 
-	percpu_inc(mce_poll_count);
+	__this_cpu_inc(mce_poll_count);
 
 	mce_gather_info(&m, NULL);
 
@@ -954,7 +954,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
 
 	atomic_inc(&mce_entry);
 
-	percpu_inc(mce_exception_count);
+	__this_cpu_inc(mce_exception_count);
 
 	if (!banks)
 		goto out;
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 5adce10..d594326 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -577,14 +577,14 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
 	/* Prefer fixed purpose counters */
 	if (x86_pmu.num_counters_fixed) {
 		idx = X86_PMC_IDX_FIXED;
-		for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_MAX) {
+		for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
 			if (!__test_and_set_bit(idx, sched->state.used))
 				goto done;
 		}
 	}
 	/* Grab the first unused counter starting with idx */
 	idx = sched->state.counter;
-	for_each_set_bit_cont(idx, c->idxmsk, X86_PMC_IDX_FIXED) {
+	for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_FIXED) {
 		if (!__test_and_set_bit(idx, sched->state.used))
 			goto done;
 	}
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 3b8a2d3..573d248 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -16,36 +16,460 @@ static u32 ibs_caps;
 
 #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
 
-static struct pmu perf_ibs;
+#include <linux/kprobes.h>
+#include <linux/hardirq.h>
+
+#include <asm/nmi.h>
+
+#define IBS_FETCH_CONFIG_MASK	(IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
+#define IBS_OP_CONFIG_MASK	IBS_OP_MAX_CNT
+
+enum ibs_states {
+	IBS_ENABLED	= 0,
+	IBS_STARTED	= 1,
+	IBS_STOPPING	= 2,
+
+	IBS_MAX_STATES,
+};
+
+struct cpu_perf_ibs {
+	struct perf_event	*event;
+	unsigned long		state[BITS_TO_LONGS(IBS_MAX_STATES)];
+};
+
+struct perf_ibs {
+	struct pmu	pmu;
+	unsigned int	msr;
+	u64		config_mask;
+	u64		cnt_mask;
+	u64		enable_mask;
+	u64		valid_mask;
+	u64		max_period;
+	unsigned long	offset_mask[1];
+	int		offset_max;
+	struct cpu_perf_ibs __percpu *pcpu;
+	u64		(*get_count)(u64 config);
+};
+
+struct perf_ibs_data {
+	u32		size;
+	union {
+		u32	data[0];	/* data buffer starts here */
+		u32	caps;
+	};
+	u64		regs[MSR_AMD64_IBS_REG_COUNT_MAX];
+};
+
+static int
+perf_event_set_period(struct hw_perf_event *hwc, u64 min, u64 max, u64 *count)
+{
+	s64 left = local64_read(&hwc->period_left);
+	s64 period = hwc->sample_period;
+	int overflow = 0;
+
+	/*
+	 * If we are way outside a reasonable range then just skip forward:
+	 */
+	if (unlikely(left <= -period)) {
+		left = period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		overflow = 1;
+	}
+
+	if (unlikely(left <= 0)) {
+		left += period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		overflow = 1;
+	}
+
+	if (unlikely(left < min))
+		left = min;
+
+	if (left > max)
+		left = max;
+
+	*count = (u64)left;
+
+	return overflow;
+}
+
+static  int
+perf_event_try_update(struct perf_event *event, u64 new_raw_count, int width)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	int shift = 64 - width;
+	u64 prev_raw_count;
+	u64 delta;
+
+	/*
+	 * Careful: an NMI might modify the previous event value.
+	 *
+	 * Our tactic to handle this is to first atomically read and
+	 * exchange a new raw count - then add that new-prev delta
+	 * count to the generic event atomically:
+	 */
+	prev_raw_count = local64_read(&hwc->prev_count);
+	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+					new_raw_count) != prev_raw_count)
+		return 0;
+
+	/*
+	 * Now we have the new raw value and have updated the prev
+	 * timestamp already. We can now calculate the elapsed delta
+	 * (event-)time and add that to the generic event.
+	 *
+	 * Careful, not all hw sign-extends above the physical width
+	 * of the count.
+	 */
+	delta = (new_raw_count << shift) - (prev_raw_count << shift);
+	delta >>= shift;
+
+	local64_add(delta, &event->count);
+	local64_sub(delta, &hwc->period_left);
+
+	return 1;
+}
+
+static struct perf_ibs perf_ibs_fetch;
+static struct perf_ibs perf_ibs_op;
+
+static struct perf_ibs *get_ibs_pmu(int type)
+{
+	if (perf_ibs_fetch.pmu.type == type)
+		return &perf_ibs_fetch;
+	if (perf_ibs_op.pmu.type == type)
+		return &perf_ibs_op;
+	return NULL;
+}
 
 static int perf_ibs_init(struct perf_event *event)
 {
-	if (perf_ibs.type != event->attr.type)
+	struct hw_perf_event *hwc = &event->hw;
+	struct perf_ibs *perf_ibs;
+	u64 max_cnt, config;
+
+	perf_ibs = get_ibs_pmu(event->attr.type);
+	if (!perf_ibs)
 		return -ENOENT;
+
+	config = event->attr.config;
+	if (config & ~perf_ibs->config_mask)
+		return -EINVAL;
+
+	if (hwc->sample_period) {
+		if (config & perf_ibs->cnt_mask)
+			/* raw max_cnt may not be set */
+			return -EINVAL;
+		if (hwc->sample_period & 0x0f)
+			/* lower 4 bits can not be set in ibs max cnt */
+			return -EINVAL;
+	} else {
+		max_cnt = config & perf_ibs->cnt_mask;
+		config &= ~perf_ibs->cnt_mask;
+		event->attr.sample_period = max_cnt << 4;
+		hwc->sample_period = event->attr.sample_period;
+	}
+
+	if (!hwc->sample_period)
+		return -EINVAL;
+
+	hwc->config_base = perf_ibs->msr;
+	hwc->config = config;
+
 	return 0;
 }
 
+static int perf_ibs_set_period(struct perf_ibs *perf_ibs,
+			       struct hw_perf_event *hwc, u64 *period)
+{
+	int ret;
+
+	/* ignore lower 4 bits in min count: */
+	ret = perf_event_set_period(hwc, 1<<4, perf_ibs->max_period, period);
+	local64_set(&hwc->prev_count, 0);
+
+	return ret;
+}
+
+static u64 get_ibs_fetch_count(u64 config)
+{
+	return (config & IBS_FETCH_CNT) >> 12;
+}
+
+static u64 get_ibs_op_count(u64 config)
+{
+	return (config & IBS_OP_CUR_CNT) >> 32;
+}
+
+static void
+perf_ibs_event_update(struct perf_ibs *perf_ibs, struct perf_event *event,
+		      u64 config)
+{
+	u64 count = perf_ibs->get_count(config);
+
+	while (!perf_event_try_update(event, count, 20)) {
+		rdmsrl(event->hw.config_base, config);
+		count = perf_ibs->get_count(config);
+	}
+}
+
+/* Note: The enable mask must be encoded in the config argument. */
+static inline void perf_ibs_enable_event(struct hw_perf_event *hwc, u64 config)
+{
+	wrmsrl(hwc->config_base, hwc->config | config);
+}
+
+/*
+ * We cannot restore the ibs pmu state, so we always needs to update
+ * the event while stopping it and then reset the state when starting
+ * again. Thus, ignoring PERF_EF_RELOAD and PERF_EF_UPDATE flags in
+ * perf_ibs_start()/perf_ibs_stop() and instead always do it.
+ */
+static void perf_ibs_start(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+	struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+	u64 config;
+
+	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
+		return;
+
+	WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+	hwc->state = 0;
+
+	perf_ibs_set_period(perf_ibs, hwc, &config);
+	config = (config >> 4) | perf_ibs->enable_mask;
+	set_bit(IBS_STARTED, pcpu->state);
+	perf_ibs_enable_event(hwc, config);
+
+	perf_event_update_userpage(event);
+}
+
+static void perf_ibs_stop(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+	struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+	u64 val;
+	int stopping;
+
+	stopping = test_and_clear_bit(IBS_STARTED, pcpu->state);
+
+	if (!stopping && (hwc->state & PERF_HES_UPTODATE))
+		return;
+
+	rdmsrl(hwc->config_base, val);
+
+	if (stopping) {
+		set_bit(IBS_STOPPING, pcpu->state);
+		val &= ~perf_ibs->enable_mask;
+		wrmsrl(hwc->config_base, val);
+		WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+		hwc->state |= PERF_HES_STOPPED;
+	}
+
+	if (hwc->state & PERF_HES_UPTODATE)
+		return;
+
+	perf_ibs_event_update(perf_ibs, event, val);
+	hwc->state |= PERF_HES_UPTODATE;
+}
+
 static int perf_ibs_add(struct perf_event *event, int flags)
 {
+	struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+	struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+	if (test_and_set_bit(IBS_ENABLED, pcpu->state))
+		return -ENOSPC;
+
+	event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	pcpu->event = event;
+
+	if (flags & PERF_EF_START)
+		perf_ibs_start(event, PERF_EF_RELOAD);
+
 	return 0;
 }
 
 static void perf_ibs_del(struct perf_event *event, int flags)
 {
+	struct perf_ibs *perf_ibs = container_of(event->pmu, struct perf_ibs, pmu);
+	struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+
+	if (!test_and_clear_bit(IBS_ENABLED, pcpu->state))
+		return;
+
+	perf_ibs_stop(event, PERF_EF_UPDATE);
+
+	pcpu->event = NULL;
+
+	perf_event_update_userpage(event);
 }
 
-static struct pmu perf_ibs = {
-	.event_init= perf_ibs_init,
-	.add= perf_ibs_add,
-	.del= perf_ibs_del,
+static void perf_ibs_read(struct perf_event *event) { }
+
+static struct perf_ibs perf_ibs_fetch = {
+	.pmu = {
+		.task_ctx_nr	= perf_invalid_context,
+
+		.event_init	= perf_ibs_init,
+		.add		= perf_ibs_add,
+		.del		= perf_ibs_del,
+		.start		= perf_ibs_start,
+		.stop		= perf_ibs_stop,
+		.read		= perf_ibs_read,
+	},
+	.msr			= MSR_AMD64_IBSFETCHCTL,
+	.config_mask		= IBS_FETCH_CONFIG_MASK,
+	.cnt_mask		= IBS_FETCH_MAX_CNT,
+	.enable_mask		= IBS_FETCH_ENABLE,
+	.valid_mask		= IBS_FETCH_VAL,
+	.max_period		= IBS_FETCH_MAX_CNT << 4,
+	.offset_mask		= { MSR_AMD64_IBSFETCH_REG_MASK },
+	.offset_max		= MSR_AMD64_IBSFETCH_REG_COUNT,
+
+	.get_count		= get_ibs_fetch_count,
 };
 
+static struct perf_ibs perf_ibs_op = {
+	.pmu = {
+		.task_ctx_nr	= perf_invalid_context,
+
+		.event_init	= perf_ibs_init,
+		.add		= perf_ibs_add,
+		.del		= perf_ibs_del,
+		.start		= perf_ibs_start,
+		.stop		= perf_ibs_stop,
+		.read		= perf_ibs_read,
+	},
+	.msr			= MSR_AMD64_IBSOPCTL,
+	.config_mask		= IBS_OP_CONFIG_MASK,
+	.cnt_mask		= IBS_OP_MAX_CNT,
+	.enable_mask		= IBS_OP_ENABLE,
+	.valid_mask		= IBS_OP_VAL,
+	.max_period		= IBS_OP_MAX_CNT << 4,
+	.offset_mask		= { MSR_AMD64_IBSOP_REG_MASK },
+	.offset_max		= MSR_AMD64_IBSOP_REG_COUNT,
+
+	.get_count		= get_ibs_op_count,
+};
+
+static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs)
+{
+	struct cpu_perf_ibs *pcpu = this_cpu_ptr(perf_ibs->pcpu);
+	struct perf_event *event = pcpu->event;
+	struct hw_perf_event *hwc = &event->hw;
+	struct perf_sample_data data;
+	struct perf_raw_record raw;
+	struct pt_regs regs;
+	struct perf_ibs_data ibs_data;
+	int offset, size, overflow, reenable;
+	unsigned int msr;
+	u64 *buf, config;
+
+	if (!test_bit(IBS_STARTED, pcpu->state)) {
+		/* Catch spurious interrupts after stopping IBS: */
+		if (!test_and_clear_bit(IBS_STOPPING, pcpu->state))
+			return 0;
+		rdmsrl(perf_ibs->msr, *ibs_data.regs);
+		return (*ibs_data.regs & perf_ibs->valid_mask) ? 1 : 0;
+	}
+
+	msr = hwc->config_base;
+	buf = ibs_data.regs;
+	rdmsrl(msr, *buf);
+	if (!(*buf++ & perf_ibs->valid_mask))
+		return 0;
+
+	perf_sample_data_init(&data, 0);
+	if (event->attr.sample_type & PERF_SAMPLE_RAW) {
+		ibs_data.caps = ibs_caps;
+		size = 1;
+		offset = 1;
+		do {
+		    rdmsrl(msr + offset, *buf++);
+		    size++;
+		    offset = find_next_bit(perf_ibs->offset_mask,
+					   perf_ibs->offset_max,
+					   offset + 1);
+		} while (offset < perf_ibs->offset_max);
+		raw.size = sizeof(u32) + sizeof(u64) * size;
+		raw.data = ibs_data.data;
+		data.raw = &raw;
+	}
+
+	regs = *iregs; /* XXX: update ip from ibs sample */
+
+	/*
+	 * Emulate IbsOpCurCnt in MSRC001_1033 (IbsOpCtl), not
+	 * supported in all cpus. As this triggered an interrupt, we
+	 * set the current count to the max count.
+	 */
+	config = ibs_data.regs[0];
+	if (perf_ibs == &perf_ibs_op && !(ibs_caps & IBS_CAPS_RDWROPCNT)) {
+		config &= ~IBS_OP_CUR_CNT;
+		config |= (config & IBS_OP_MAX_CNT) << 36;
+	}
+
+	perf_ibs_event_update(perf_ibs, event, config);
+
+	overflow = perf_ibs_set_period(perf_ibs, hwc, &config);
+	reenable = !(overflow && perf_event_overflow(event, &data, &regs));
+	config = (config >> 4) | (reenable ? perf_ibs->enable_mask : 0);
+	perf_ibs_enable_event(hwc, config);
+
+	perf_event_update_userpage(event);
+
+	return 1;
+}
+
+static int __kprobes
+perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs)
+{
+	int handled = 0;
+
+	handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs);
+	handled += perf_ibs_handle_irq(&perf_ibs_op, regs);
+
+	if (handled)
+		inc_irq_stat(apic_perf_irqs);
+
+	return handled;
+}
+
+static __init int perf_ibs_pmu_init(struct perf_ibs *perf_ibs, char *name)
+{
+	struct cpu_perf_ibs __percpu *pcpu;
+	int ret;
+
+	pcpu = alloc_percpu(struct cpu_perf_ibs);
+	if (!pcpu)
+		return -ENOMEM;
+
+	perf_ibs->pcpu = pcpu;
+
+	ret = perf_pmu_register(&perf_ibs->pmu, name, -1);
+	if (ret) {
+		perf_ibs->pcpu = NULL;
+		free_percpu(pcpu);
+	}
+
+	return ret;
+}
+
 static __init int perf_event_ibs_init(void)
 {
 	if (!ibs_caps)
 		return -ENODEV;	/* ibs not supported by the cpu */
 
-	perf_pmu_register(&perf_ibs, "ibs", -1);
+	perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
+	perf_ibs_pmu_init(&perf_ibs_op, "ibs_op");
+	register_nmi_handler(NMI_LOCAL, &perf_ibs_nmi_handler, 0, "perf_ibs");
 	printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps);
 
 	return 0;
diff --git a/arch/x86/kernel/crash_dump_32.c b/arch/x86/kernel/crash_dump_32.c
index 642f75a..11891ca 100644
--- a/arch/x86/kernel/crash_dump_32.c
+++ b/arch/x86/kernel/crash_dump_32.c
@@ -62,16 +62,16 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
 
 	if (!userbuf) {
 		memcpy(buf, (vaddr + offset), csize);
-		kunmap_atomic(vaddr, KM_PTE0);
+		kunmap_atomic(vaddr);
 	} else {
 		if (!kdump_buf_page) {
 			printk(KERN_WARNING "Kdump: Kdump buffer page not"
 				" allocated\n");
-			kunmap_atomic(vaddr, KM_PTE0);
+			kunmap_atomic(vaddr);
 			return -EFAULT;
 		}
 		copy_page(kdump_buf_page, vaddr);
-		kunmap_atomic(vaddr, KM_PTE0);
+		kunmap_atomic(vaddr);
 		if (copy_to_user(buf, (kdump_buf_page + offset), csize))
 			return -EFAULT;
 	}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 313fb5c..43e2b1c 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -306,10 +306,10 @@ void __init native_init_IRQ(void)
 	 * us. (some of these will be overridden and become
 	 * 'special' SMP interrupts)
 	 */
-	for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
+	i = FIRST_EXTERNAL_VECTOR;
+	for_each_clear_bit_from(i, used_vectors, NR_VECTORS) {
 		/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
-		if (!test_bit(i, used_vectors))
-			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
+		set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
 	}
 
 	if (!acpi_ioapic && !of_ioapic)
diff --git a/arch/x86/kernel/nmi_selftest.c b/arch/x86/kernel/nmi_selftest.c
index 0d01a8e..8aca005 100644
--- a/arch/x86/kernel/nmi_selftest.c
+++ b/arch/x86/kernel/nmi_selftest.c
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/delay.h>
+#include <linux/percpu.h>
 
 #include <asm/apic.h>
 #include <asm/nmi.h>
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index d90272e..2f0c1d1 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -239,16 +239,16 @@ static DEFINE_PER_CPU(enum paravirt_lazy_mode, paravirt_lazy_mode) = PARAVIRT_LA
 
 static inline void enter_lazy(enum paravirt_lazy_mode mode)
 {
-	BUG_ON(percpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
+	BUG_ON(__this_cpu_read(paravirt_lazy_mode) != PARAVIRT_LAZY_NONE);
 
-	percpu_write(paravirt_lazy_mode, mode);
+	__this_cpu_write(paravirt_lazy_mode, mode);
 }
 
 static void leave_lazy(enum paravirt_lazy_mode mode)
 {
-	BUG_ON(percpu_read(paravirt_lazy_mode) != mode);
+	BUG_ON(__this_cpu_read(paravirt_lazy_mode) != mode);
 
-	percpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
+	__this_cpu_write(paravirt_lazy_mode, PARAVIRT_LAZY_NONE);
 }
 
 void paravirt_enter_lazy_mmu(void)
@@ -265,7 +265,7 @@ void paravirt_start_context_switch(struct task_struct *prev)
 {
 	BUG_ON(preemptible());
 
-	if (percpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
+	if (__this_cpu_read(paravirt_lazy_mode) == PARAVIRT_LAZY_MMU) {
 		arch_leave_lazy_mmu_mode();
 		set_ti_thread_flag(task_thread_info(prev), TIF_LAZY_MMU_UPDATES);
 	}
@@ -287,7 +287,7 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
 	if (in_interrupt())
 		return PARAVIRT_LAZY_NONE;
 
-	return percpu_read(paravirt_lazy_mode);
+	return __this_cpu_read(paravirt_lazy_mode);
 }
 
 void arch_flush_lazy_mmu_mode(void)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 485204f..6acfb80 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -377,7 +377,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 	if (prev->gs | next->gs)
 		lazy_load_gs(next->gs);
 
-	percpu_write(current_task, next_p);
+	__this_cpu_write(current_task, next_p);
 
 	return prev_p;
 }
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9b9fe4a..1b434d3 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
 
 void enter_idle(void)
 {
-	percpu_write(is_idle, 1);
+	__this_cpu_write(is_idle, 1);
 	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
 }
 
@@ -343,7 +343,7 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
 	load_gs_index(0);
 	regs->ip		= new_ip;
 	regs->sp		= new_sp;
-	percpu_write(old_rsp, new_sp);
+	this_cpu_write(old_rsp, new_sp);
 	regs->cs		= _cs;
 	regs->ss		= _ss;
 	regs->flags		= X86_EFLAGS_IF;
@@ -477,11 +477,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 	/*
 	 * Switch the PDA and FPU contexts.
 	 */
-	prev->usersp = percpu_read(old_rsp);
-	percpu_write(old_rsp, next->usersp);
-	percpu_write(current_task, next_p);
+	prev->usersp = __this_cpu_read(old_rsp);
+	__this_cpu_write(old_rsp, next->usersp);
+	__this_cpu_write(current_task, next_p);
 
-	percpu_write(kernel_stack,
+	__this_cpu_write(kernel_stack,
 		  (unsigned long)task_stack_page(next_p) +
 		  THREAD_SIZE - KERNEL_STACK_OFFSET);
 
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 46a01bd..f190103 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -20,6 +20,7 @@
 #include <linux/personality.h>
 #include <linux/uaccess.h>
 #include <linux/user-return-notifier.h>
+#include <linux/uprobes.h>
 
 #include <asm/processor.h>
 #include <asm/ucontext.h>
@@ -816,6 +817,11 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 		mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
+	if (thread_info_flags & _TIF_UPROBE) {
+		clear_thread_flag(TIF_UPROBE);
+		uprobe_notify_resume(regs);
+	}
+
 	/* deal with pending signal delivery */
 	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs);
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
new file mode 100644
index 0000000..9fd1106
--- /dev/null
+++ b/arch/x86/kernel/uprobes.c
@@ -0,0 +1,674 @@
+/*
+ * Userspace Probes (UProbes) for x86
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2008-2011
+ * Authors:
+ *	Srikar Dronamraju
+ *	Jim Keniston
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+
+#include <linux/kdebug.h>
+#include <asm/insn.h>
+
+#ifdef CONFIG_X86_32
+#define is_32bit_app(tsk) 1
+#else
+#define is_32bit_app(tsk) (test_tsk_thread_flag(tsk, TIF_IA32))
+#endif
+
+/* Post-execution fixups. */
+
+/* No fixup needed */
+#define UPROBES_FIX_NONE	0x0
+/* Adjust IP back to vicinity of actual insn */
+#define UPROBES_FIX_IP		0x1
+/* Adjust the return address of a call insn */
+#define UPROBES_FIX_CALL	0x2
+
+#define UPROBES_FIX_RIP_AX	0x8000
+#define UPROBES_FIX_RIP_CX	0x4000
+
+/* Adaptations for mhiramat x86 decoder v14. */
+#define OPCODE1(insn) ((insn)->opcode.bytes[0])
+#define OPCODE2(insn) ((insn)->opcode.bytes[1])
+#define OPCODE3(insn) ((insn)->opcode.bytes[2])
+#define MODRM_REG(insn) X86_MODRM_REG(insn->modrm.value)
+
+#define W(row, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf)\
+	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
+	  (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
+	  (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
+	  (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
+	 << (row % 32))
+
+#ifdef CONFIG_X86_64
+static volatile u32 good_insns_64[256 / 32] = {
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+	/*      ----------------------------------------------         */
+	W(0x00, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 00 */
+	W(0x10, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 10 */
+	W(0x20, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) | /* 20 */
+	W(0x30, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0) , /* 30 */
+	W(0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) | /* 40 */
+	W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
+	W(0x60, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
+	W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */
+	W(0x80, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
+	W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
+	W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */
+	W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
+	W(0xc0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */
+	W(0xd0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
+	W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */
+	W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1)   /* f0 */
+	/*      ----------------------------------------------         */
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+};
+#endif
+
+/* Good-instruction tables for 32-bit apps */
+
+static volatile u32 good_insns_32[256 / 32] = {
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+	/*      ----------------------------------------------         */
+	W(0x00, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) | /* 00 */
+	W(0x10, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) , /* 10 */
+	W(0x20, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) | /* 20 */
+	W(0x30, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1) , /* 30 */
+	W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
+	W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
+	W(0x60, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* 60 */
+	W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 70 */
+	W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
+	W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
+	W(0xa0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* a0 */
+	W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
+	W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0) | /* c0 */
+	W(0xd0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
+	W(0xe0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0) | /* e0 */
+	W(0xf0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1)   /* f0 */
+	/*      ----------------------------------------------         */
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+};
+
+/* Using this for both 64-bit and 32-bit apps */
+static volatile u32 good_2byte_insns[256 / 32] = {
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+	/*      ----------------------------------------------         */
+	W(0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1) | /* 00 */
+	W(0x10, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* 10 */
+	W(0x20, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1) | /* 20 */
+	W(0x30, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) , /* 30 */
+	W(0x40, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 40 */
+	W(0x50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 50 */
+	W(0x60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 60 */
+	W(0x70, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1) , /* 70 */
+	W(0x80, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* 80 */
+	W(0x90, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* 90 */
+	W(0xa0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1) | /* a0 */
+	W(0xb0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1) , /* b0 */
+	W(0xc0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* c0 */
+	W(0xd0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) , /* d0 */
+	W(0xe0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) | /* e0 */
+	W(0xf0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)   /* f0 */
+	/*      ----------------------------------------------         */
+	/*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f         */
+};
+
+#undef W
+
+/*
+ * opcodes we'll probably never support:
+ * 6c-6d, e4-e5, ec-ed - in
+ * 6e-6f, e6-e7, ee-ef - out
+ * cc, cd - int3, int
+ * cf - iret
+ * d6 - illegal instruction
+ * f1 - int1/icebp
+ * f4 - hlt
+ * fa, fb - cli, sti
+ * 0f - lar, lsl, syscall, clts, sysret, sysenter, sysexit, invd, wbinvd, ud2
+ *
+ * invalid opcodes in 64-bit mode:
+ * 06, 0e, 16, 1e, 27, 2f, 37, 3f, 60-62, 82, c4-c5, d4-d5
+ *
+ * 63 - we support this opcode in x86_64 but not in i386.
+ *
+ * opcodes we may need to refine support for:
+ * 0f - 2-byte instructions: For many of these instructions, the validity
+ * depends on the prefix and/or the reg field.  On such instructions, we
+ * just consider the opcode combination valid if it corresponds to any
+ * valid instruction.
+ * 8f - Group 1 - only reg = 0 is OK
+ * c6-c7 - Group 11 - only reg = 0 is OK
+ * d9-df - fpu insns with some illegal encodings
+ * f2, f3 - repnz, repz prefixes.  These are also the first byte for
+ * certain floating-point instructions, such as addsd.
+ * fe - Group 4 - only reg = 0 or 1 is OK
+ * ff - Group 5 - only reg = 0-6 is OK
+ *
+ * others -- Do we need to support these?
+ * 0f - (floating-point?) prefetch instructions
+ * 07, 17, 1f - pop es, pop ss, pop ds
+ * 26, 2e, 36, 3e - es:, cs:, ss:, ds: segment prefixes --
+ *	but 64 and 65 (fs: and gs:) seem to be used, so we support them
+ * 67 - addr16 prefix
+ * ce - into
+ * f0 - lock prefix
+ */
+
+/*
+ * TODO:
+ * - Where necessary, examine the modrm byte and allow only valid instructions
+ * in the different Groups and fpu instructions.
+ */
+
+static bool is_prefix_bad(struct insn *insn)
+{
+	int i;
+
+	for (i = 0; i < insn->prefixes.nbytes; i++) {
+		switch (insn->prefixes.bytes[i]) {
+		case 0x26:	/*INAT_PFX_ES   */
+		case 0x2E:	/*INAT_PFX_CS   */
+		case 0x36:	/*INAT_PFX_DS   */
+		case 0x3E:	/*INAT_PFX_SS   */
+		case 0xF0:	/*INAT_PFX_LOCK */
+			return true;
+		}
+	}
+	return false;
+}
+
+static int validate_insn_32bits(struct uprobe *uprobe, struct insn *insn)
+{
+	insn_init(insn, uprobe->insn, false);
+
+	/* Skip good instruction prefixes; reject "bad" ones. */
+	insn_get_opcode(insn);
+	if (is_prefix_bad(insn))
+		return -ENOTSUPP;
+	if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_32))
+		return 0;
+	if (insn->opcode.nbytes == 2) {
+		if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
+			return 0;
+	}
+	return -ENOTSUPP;
+}
+
+/*
+ * Figure out which fixups post_xol() will need to perform, and annotate
+ * uprobe->arch_info.fixups accordingly.  To start with,
+ * uprobe->arch_info.fixups is either zero or it reflects rip-related
+ * fixups.
+ */
+static void prepare_fixups(struct uprobe *uprobe, struct insn *insn)
+{
+	bool fix_ip = true, fix_call = false;	/* defaults */
+	int reg;
+
+	insn_get_opcode(insn);	/* should be a nop */
+
+	switch (OPCODE1(insn)) {
+	case 0xc3:		/* ret/lret */
+	case 0xcb:
+	case 0xc2:
+	case 0xca:
+		/* ip is correct */
+		fix_ip = false;
+		break;
+	case 0xe8:		/* call relative - Fix return addr */
+		fix_call = true;
+		break;
+	case 0x9a:		/* call absolute - Fix return addr, not ip */
+		fix_call = true;
+		fix_ip = false;
+		break;
+	case 0xff:
+		insn_get_modrm(insn);
+		reg = MODRM_REG(insn);
+		if (reg == 2 || reg == 3) {
+			/* call or lcall, indirect */
+			/* Fix return addr; ip is correct. */
+			fix_call = true;
+			fix_ip = false;
+		} else if (reg == 4 || reg == 5) {
+			/* jmp or ljmp, indirect */
+			/* ip is correct. */
+			fix_ip = false;
+		}
+		break;
+	case 0xea:		/* jmp absolute -- ip is correct */
+		fix_ip = false;
+		break;
+	default:
+		break;
+	}
+	if (fix_ip)
+		uprobe->arch_info.fixups |= UPROBES_FIX_IP;
+	if (fix_call)
+		uprobe->arch_info.fixups |= UPROBES_FIX_CALL;
+}
+
+#ifdef CONFIG_X86_64
+/*
+ * If uprobe->insn doesn't use rip-relative addressing, return
+ * immediately.  Otherwise, rewrite the instruction so that it accesses
+ * its memory operand indirectly through a scratch register.  Set
+ * uprobe->arch_info.fixups and uprobe->arch_info.rip_rela_target_address
+ * accordingly.  (The contents of the scratch register will be saved
+ * before we single-step the modified instruction, and restored
+ * afterward.)
+ *
+ * We do this because a rip-relative instruction can access only a
+ * relatively small area (+/- 2 GB from the instruction), and the XOL
+ * area typically lies beyond that area.  At least for instructions
+ * that store to memory, we can't execute the original instruction
+ * and "fix things up" later, because the misdirected store could be
+ * disastrous.
+ *
+ * Some useful facts about rip-relative instructions:
+ * - There's always a modrm byte.
+ * - There's never a SIB byte.
+ * - The displacement is always 4 bytes.
+ */
+static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe,
+							struct insn *insn)
+{
+	u8 *cursor;
+	u8 reg;
+
+	if (mm->context.ia32_compat)
+		return;
+
+	uprobe->arch_info.rip_rela_target_address = 0x0;
+	if (!insn_rip_relative(insn))
+		return;
+
+	/*
+	 * Point cursor at the modrm byte.  The next 4 bytes are the
+	 * displacement.  Beyond the displacement, for some instructions,
+	 * is the immediate operand.
+	 */
+	cursor = uprobe->insn + insn->prefixes.nbytes
+			+ insn->rex_prefix.nbytes + insn->opcode.nbytes;
+	insn_get_length(insn);
+
+	/*
+	 * Convert from rip-relative addressing to indirect addressing
+	 * via a scratch register.  Change the r/m field from 0x5 (%rip)
+	 * to 0x0 (%rax) or 0x1 (%rcx), and squeeze out the offset field.
+	 */
+	reg = MODRM_REG(insn);
+	if (reg == 0) {
+		/*
+		 * The register operand (if any) is either the A register
+		 * (%rax, %eax, etc.) or (if the 0x4 bit is set in the
+		 * REX prefix) %r8.  In any case, we know the C register
+		 * is NOT the register operand, so we use %rcx (register
+		 * #1) for the scratch register.
+		 */
+		uprobe->arch_info.fixups = UPROBES_FIX_RIP_CX;
+		/* Change modrm from 00 000 101 to 00 000 001. */
+		*cursor = 0x1;
+	} else {
+		/* Use %rax (register #0) for the scratch register. */
+		uprobe->arch_info.fixups = UPROBES_FIX_RIP_AX;
+		/* Change modrm from 00 xxx 101 to 00 xxx 000 */
+		*cursor = (reg << 3);
+	}
+
+	/* Target address = address of next instruction + (signed) offset */
+	uprobe->arch_info.rip_rela_target_address = (long)insn->length
+					+ insn->displacement.value;
+	/* Displacement field is gone; slide immediate field (if any) over. */
+	if (insn->immediate.nbytes) {
+		cursor++;
+		memmove(cursor, cursor + insn->displacement.nbytes,
+						insn->immediate.nbytes);
+	}
+	return;
+}
+
+static int validate_insn_64bits(struct uprobe *uprobe, struct insn *insn)
+{
+	insn_init(insn, uprobe->insn, true);
+
+	/* Skip good instruction prefixes; reject "bad" ones. */
+	insn_get_opcode(insn);
+	if (is_prefix_bad(insn))
+		return -ENOTSUPP;
+	if (test_bit(OPCODE1(insn), (unsigned long *)good_insns_64))
+		return 0;
+	if (insn->opcode.nbytes == 2) {
+		if (test_bit(OPCODE2(insn), (unsigned long *)good_2byte_insns))
+			return 0;
+	}
+	return -ENOTSUPP;
+}
+
+static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe,
+				struct insn *insn)
+{
+	if (mm->context.ia32_compat)
+		return validate_insn_32bits(uprobe, insn);
+	return validate_insn_64bits(uprobe, insn);
+}
+#else
+static void handle_riprel_insn(struct mm_struct *mm, struct uprobe *uprobe,
+							struct insn *insn)
+{
+	return;
+}
+
+static int validate_insn_bits(struct mm_struct *mm, struct uprobe *uprobe,
+				struct insn *insn)
+{
+	return validate_insn_32bits(uprobe, insn);
+}
+#endif /* CONFIG_X86_64 */
+
+/**
+ * analyze_insn - instruction analysis including validity and fixups.
+ * @mm: the probed address space.
+ * @uprobe: the probepoint information.
+ * Return 0 on success or a -ve number on error.
+ */
+int analyze_insn(struct mm_struct *mm, struct uprobe *uprobe)
+{
+	int ret;
+	struct insn insn;
+
+	uprobe->arch_info.fixups = 0;
+	ret = validate_insn_bits(mm, uprobe, &insn);
+	if (ret != 0)
+		return ret;
+	handle_riprel_insn(mm, uprobe, &insn);
+	prepare_fixups(uprobe, &insn);
+	return 0;
+}
+
+/*
+ * @reg: reflects the saved state of the task
+ * @vaddr: the virtual address to jump to.
+ */
+void set_instruction_pointer(struct pt_regs *regs, unsigned long vaddr)
+{
+	regs->ip = vaddr;
+}
+
+#define	UPROBE_TRAP_NO		UINT_MAX
+
+/*
+ * pre_xol - prepare to execute out of line.
+ * @uprobe: the probepoint information.
+ * @regs: reflects the saved user state of @tsk.
+ *
+ * If we're emulating a rip-relative instruction, save the contents
+ * of the scratch register and store the target address in that register.
+ *
+ * Returns true if @uprobe->opcode is @bkpt_insn.
+ */
+#ifdef CONFIG_X86_64
+int pre_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_task_arch_info *tskinfo = &current->utask->tskinfo;
+
+	tskinfo->saved_trap_no = current->thread.trap_no;
+	current->thread.trap_no = UPROBE_TRAP_NO;
+
+	regs->ip = current->utask->xol_vaddr;
+	if (uprobe->arch_info.fixups & UPROBES_FIX_RIP_AX) {
+		tskinfo->saved_scratch_register = regs->ax;
+		regs->ax = current->utask->vaddr;
+		regs->ax += uprobe->arch_info.rip_rela_target_address;
+	} else if (uprobe->arch_info.fixups & UPROBES_FIX_RIP_CX) {
+		tskinfo->saved_scratch_register = regs->cx;
+		regs->cx = current->utask->vaddr;
+		regs->cx += uprobe->arch_info.rip_rela_target_address;
+	}
+	return 0;
+}
+#else
+int pre_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_task_arch_info *tskinfo = &current->utask->tskinfo;
+
+	tskinfo->saved_trap_no = current->thread.trap_no;
+	current->thread.trap_no = UPROBE_TRAP_NO;
+
+	regs->ip = current->utask->xol_vaddr;
+	return 0;
+}
+#endif
+
+/*
+ * Called by post_xol() to adjust the return address pushed by a call
+ * instruction executed out of line.
+ */
+static int adjust_ret_addr(unsigned long sp, long correction)
+{
+	int rasize, ncopied;
+	long ra = 0;
+
+	if (is_32bit_app(current))
+		rasize = 4;
+	else
+		rasize = 8;
+
+	ncopied = copy_from_user(&ra, (void __user *)sp, rasize);
+	if (unlikely(ncopied))
+		return -EFAULT;
+
+	ra += correction;
+	ncopied = copy_to_user((void __user *)sp, &ra, rasize);
+	if (unlikely(ncopied))
+		return -EFAULT;
+
+	return 0;
+}
+
+#ifdef CONFIG_X86_64
+static bool is_riprel_insn(struct uprobe *uprobe)
+{
+	return ((uprobe->arch_info.fixups &
+			(UPROBES_FIX_RIP_AX | UPROBES_FIX_RIP_CX)) != 0);
+}
+
+static void handle_riprel_post_xol(struct uprobe *uprobe,
+			struct pt_regs *regs, long *correction)
+{
+	if (is_riprel_insn(uprobe)) {
+		struct uprobe_task_arch_info *tskinfo;
+		tskinfo = &current->utask->tskinfo;
+
+		if (uprobe->arch_info.fixups & UPROBES_FIX_RIP_AX)
+			regs->ax = tskinfo->saved_scratch_register;
+		else
+			regs->cx = tskinfo->saved_scratch_register;
+		/*
+		 * The original instruction includes a displacement, and so
+		 * is 4 bytes longer than what we've just single-stepped.
+		 * Fall through to handle stuff like "jmpq *...(%rip)" and
+		 * "callq *...(%rip)".
+		 */
+		if (correction)
+			*correction += 4;
+	}
+}
+#else
+static void handle_riprel_post_xol(struct uprobe *uprobe,
+			struct pt_regs *regs, long *correction)
+{
+}
+#endif
+
+/*
+ * If xol insn itself traps and generates a signal(Say,
+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
+ * instruction jumps back to its own address. It is assumed that anything
+ * like do_page_fault/do_trap/etc sets thread.trap_no != -1.
+ *
+ * pre_xol/post_xol save/restore thread.trap_no, xol_was_trapped() simply
+ * checks that ->trap_no is not equal to UPROBE_TRAP_NO == -1 set by
+ * pre_xol().
+ */
+bool xol_was_trapped(struct task_struct *tsk)
+{
+	if (tsk->thread.trap_no != UPROBE_TRAP_NO)
+		return true;
+
+	return false;
+}
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ * We have to fix things up as follows:
+ *
+ * Typically, the new ip is relative to the copied instruction.  We need
+ * to make it relative to the original instruction (FIX_IP).  Exceptions
+ * are return instructions and absolute or indirect jump or call instructions.
+ *
+ * If the single-stepped instruction was a call, the return address that
+ * is atop the stack is the address following the copied instruction.  We
+ * need to make it the address following the original instruction (FIX_CALL).
+ *
+ * If the original instruction was a rip-relative instruction such as
+ * "movl %edx,0xnnnn(%rip)", we have instead executed an equivalent
+ * instruction using a scratch register -- e.g., "movl %edx,(%rax)".
+ * We need to restore the contents of the scratch register and adjust
+ * the ip, keeping in mind that the instruction we executed is 4 bytes
+ * shorter than the original instruction (since we squeezed out the offset
+ * field).  (FIX_RIP_AX or FIX_RIP_CX)
+ */
+int post_xol(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+	int result = 0;
+	long correction;
+
+	WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NO);
+
+	current->thread.trap_no = utask->tskinfo.saved_trap_no;
+	correction = (long)(utask->vaddr - utask->xol_vaddr);
+	handle_riprel_post_xol(uprobe, regs, &correction);
+	if (uprobe->arch_info.fixups & UPROBES_FIX_IP)
+		regs->ip += correction;
+	if (uprobe->arch_info.fixups & UPROBES_FIX_CALL)
+		result = adjust_ret_addr(regs->sp, correction);
+	return result;
+}
+
+/*
+ * Wrapper routine for handling exceptions.
+ */
+int uprobe_exception_notify(struct notifier_block *self,
+				       unsigned long val, void *data)
+{
+	struct die_args *args = data;
+	struct pt_regs *regs = args->regs;
+	int ret = NOTIFY_DONE;
+
+	/* We are only interested in userspace traps */
+	if (regs && !user_mode_vm(regs))
+		return NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_INT3:
+		/* Run your handler here */
+		if (uprobe_bkpt_notifier(regs))
+			ret = NOTIFY_STOP;
+		break;
+	case DIE_DEBUG:
+		if (uprobe_post_notifier(regs))
+			ret = NOTIFY_STOP;
+	default:
+		break;
+	}
+	return ret;
+}
+
+/*
+ * xol insn either trapped or thread has a fatal signal, so reset the
+ * instruction pointer to its probed address.
+ */
+void abort_xol(struct pt_regs *regs, struct uprobe *uprobe)
+{
+	struct uprobe_task *utask = current->utask;
+
+	current->thread.trap_no = utask->tskinfo.saved_trap_no;
+	handle_riprel_post_xol(uprobe, regs, NULL);
+	set_instruction_pointer(regs, utask->vaddr);
+}
+
+/*
+ * Skip these instructions:
+ *
+ * 0f 19 90 90 90 90 90		nopl   -0x6f6f6f70(%rax)
+ * 0f 1f 00			nopl (%rax)
+ * 0f 1f 40 00			nopl 0x0(%rax)
+ * 0f 1f 44 00 00		nopl 0x0(%rax,%rax,1)
+ * 0f 1f 80 00 00 00 00		nopl 0x0(%rax)
+ * 0f 1f 84 00 00 00 00		nopl 0x0(%rax,%rax,1)
+ * 66 0f 1f 44 00 00 00		nopw 0x0(%rax,%rax,1)
+ * 66 0f 1f 84 00 00 00		nopw 0x0(%rax,%rax,1)
+ * 66 87 c0			xchg %eax,%eax
+ * 66 90			nop
+ * 87 c0			xchg %eax,%eax
+ * 90 				nop
+ */
+
+bool can_skip_xol(struct pt_regs *regs, struct uprobe *u)
+{
+	int i;
+
+	for (i = 0; i < MAX_UINSN_BYTES; i++) {
+		if ((u->insn[i] == 0x66))
+			continue;
+
+		if (u->insn[i] == 0x90)
+			return true;
+
+		if (i == (MAX_UINSN_BYTES - 1))
+			break;
+
+		if ((u->insn[i] == 0x0f) && (u->insn[i+1] == 0x1f))
+			return true;
+
+		if ((u->insn[i] == 0x0f) && (u->insn[i+1] == 0x19))
+			return true;
+
+		if ((u->insn[i] == 0x87) && (u->insn[i+1] == 0xc0))
+			return true;
+
+		break;
+	}
+
+	u->flags &= ~UPROBES_SKIP_SSTEP;
+	return false;
+}
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index cfdc6e0..31bfc69 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1283,9 +1283,9 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu)
 	if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr)
 		return;
 
-	vapic = kmap_atomic(vcpu->arch.apic->vapic_page, KM_USER0);
+	vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
 	data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr));
-	kunmap_atomic(vapic, KM_USER0);
+	kunmap_atomic(vapic);
 
 	apic_set_tpr(vcpu->arch.apic, data & 0xff);
 }
@@ -1310,9 +1310,9 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
 		max_isr = 0;
 	data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24);
 
-	vapic = kmap_atomic(vcpu->arch.apic->vapic_page, KM_USER0);
+	vapic = kmap_atomic(vcpu->arch.apic->vapic_page);
 	*(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data;
-	kunmap_atomic(vapic, KM_USER0);
+	kunmap_atomic(vapic);
 }
 
 void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr)
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 1561028..df5a703 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -92,9 +92,9 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 	if (unlikely(npages != 1))
 		return -EFAULT;
 
-	table = kmap_atomic(page, KM_USER0);
+	table = kmap_atomic(page);
 	ret = CMPXCHG(&table[index], orig_pte, new_pte);
-	kunmap_atomic(table, KM_USER0);
+	kunmap_atomic(table);
 
 	kvm_release_page_dirty(page);
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 14d6cad..caa2543 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1162,12 +1162,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 	 */
 	vcpu->hv_clock.version += 2;
 
-	shared_kaddr = kmap_atomic(vcpu->time_page, KM_USER0);
+	shared_kaddr = kmap_atomic(vcpu->time_page);
 
 	memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
 	       sizeof(vcpu->hv_clock));
 
-	kunmap_atomic(shared_kaddr, KM_USER0);
+	kunmap_atomic(shared_kaddr);
 
 	mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
 	return 0;
@@ -3826,7 +3826,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 		goto emul_write;
 	}
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	kaddr += offset_in_page(gpa);
 	switch (bytes) {
 	case 1:
@@ -3844,7 +3844,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 	default:
 		BUG();
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	kvm_release_page_dirty(page);
 
 	if (!exchanged)
diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S
index 01c805b..6b34d04 100644
--- a/arch/x86/lib/copy_page_64.S
+++ b/arch/x86/lib/copy_page_64.S
@@ -20,14 +20,12 @@ ENDPROC(copy_page_c)
 
 ENTRY(copy_page)
 	CFI_STARTPROC
-	subq	$3*8,%rsp
-	CFI_ADJUST_CFA_OFFSET 3*8
+	subq	$2*8,%rsp
+	CFI_ADJUST_CFA_OFFSET 2*8
 	movq	%rbx,(%rsp)
 	CFI_REL_OFFSET rbx, 0
 	movq	%r12,1*8(%rsp)
 	CFI_REL_OFFSET r12, 1*8
-	movq	%r13,2*8(%rsp)
-	CFI_REL_OFFSET r13, 2*8
 
 	movl	$(4096/64)-5,%ecx
 	.p2align 4
@@ -91,10 +89,8 @@ ENTRY(copy_page)
 	CFI_RESTORE rbx
 	movq	1*8(%rsp),%r12
 	CFI_RESTORE r12
-	movq	2*8(%rsp),%r13
-	CFI_RESTORE r13
-	addq	$3*8,%rsp
-	CFI_ADJUST_CFA_OFFSET -3*8
+	addq	$2*8,%rsp
+	CFI_ADJUST_CFA_OFFSET -2*8
 	ret
 .Lcopy_page_end:
 	CFI_ENDPROC
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index e218d5d..d9b094c 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -760,9 +760,9 @@ survive:
 				break;
 			}
 
-			maddr = kmap_atomic(pg, KM_USER0);
+			maddr = kmap_atomic(pg);
 			memcpy(maddr + offset, from, len);
-			kunmap_atomic(maddr, KM_USER0);
+			kunmap_atomic(maddr);
 			set_page_dirty_lock(pg);
 			put_page(pg);
 			up_read(&current->mm->mmap_sem);
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c
index f4f29b1..6f31ee5 100644
--- a/arch/x86/mm/highmem_32.c
+++ b/arch/x86/mm/highmem_32.c
@@ -51,11 +51,11 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void *__kmap_atomic(struct page *page)
+void *kmap_atomic(struct page *page)
 {
 	return kmap_atomic_prot(page, kmap_prot);
 }
-EXPORT_SYMBOL(__kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic);
 
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 6cabf65..2e92fdc 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -30,8 +30,14 @@ int direct_gbpages
 #endif
 ;
 
-static void __init find_early_table_space(unsigned long end, int use_pse,
-					  int use_gbpages)
+struct map_range {
+	unsigned long start;
+	unsigned long end;
+	unsigned page_size_mask;
+};
+
+static void __init find_early_table_space(struct map_range *mr, unsigned long end,
+					  int use_pse, int use_gbpages)
 {
 	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
 	phys_addr_t base;
@@ -56,6 +62,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
 #ifdef CONFIG_X86_32
 		extra += PMD_SIZE;
 #endif
+		/* The first 2/4M doesn't use large pages. */
+		extra += mr->end - mr->start;
+
 		ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	} else
 		ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -85,12 +94,6 @@ void __init native_pagetable_reserve(u64 start, u64 end)
 	memblock_reserve(start, end - start);
 }
 
-struct map_range {
-	unsigned long start;
-	unsigned long end;
-	unsigned page_size_mask;
-};
-
 #ifdef CONFIG_X86_32
 #define NR_RANGE_MR 3
 #else /* CONFIG_X86_64 */
@@ -262,7 +265,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
 	 * nodes are discovered.
 	 */
 	if (!after_bootmem)
-		find_early_table_space(end, use_pse, use_gbpages);
+		find_early_table_space(&mr[0], end, use_pse, use_gbpages);
 
 	for (i = 0; i < nr_range; i++)
 		ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index d6c0418..e931db0 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -61,10 +61,10 @@ static DEFINE_PER_CPU_READ_MOSTLY(int, tlb_vector_offset);
  */
 void leave_mm(int cpu)
 {
-	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
+	if (__this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK)
 		BUG();
 	cpumask_clear_cpu(cpu,
-			  mm_cpumask(percpu_read(cpu_tlbstate.active_mm)));
+			  mm_cpumask(__this_cpu_read(cpu_tlbstate.active_mm)));
 	load_cr3(swapper_pg_dir);
 }
 EXPORT_SYMBOL_GPL(leave_mm);
@@ -152,8 +152,8 @@ void smp_invalidate_interrupt(struct pt_regs *regs)
 		 * BUG();
 		 */
 
-	if (f->flush_mm == percpu_read(cpu_tlbstate.active_mm)) {
-		if (percpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
+	if (f->flush_mm == __this_cpu_read(cpu_tlbstate.active_mm)) {
+		if (__this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
 			if (f->flush_va == TLB_FLUSH_ALL)
 				local_flush_tlb();
 			else
@@ -322,7 +322,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
 static void do_flush_tlb_all(void *info)
 {
 	__flush_tlb_all();
-	if (percpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
+	if (__this_cpu_read(cpu_tlbstate.state) == TLBSTATE_LAZY)
 		leave_mm(smp_processor_id());
 }
 
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 7b65f75..7c1b765 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -151,17 +151,18 @@ void bpf_jit_compile(struct sk_filter *fp)
 	cleanup_addr = proglen; /* epilogue address */
 
 	for (pass = 0; pass < 10; pass++) {
+		u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
 		/* no prologue/epilogue for trivial filters (RET something) */
 		proglen = 0;
 		prog = temp;
 
-		if (seen) {
+		if (seen_or_pass0) {
 			EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
 			EMIT4(0x48, 0x83, 0xec, 96);	/* subq  $96,%rsp	*/
 			/* note : must save %rbx in case bpf_error is hit */
-			if (seen & (SEEN_XREG | SEEN_DATAREF))
+			if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF))
 				EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
-			if (seen & SEEN_XREG)
+			if (seen_or_pass0 & SEEN_XREG)
 				CLEAR_X(); /* make sure we dont leek kernel memory */
 
 			/*
@@ -170,7 +171,7 @@ void bpf_jit_compile(struct sk_filter *fp)
 			 *  r9 = skb->len - skb->data_len
 			 *  r8 = skb->data
 			 */
-			if (seen & SEEN_DATAREF) {
+			if (seen_or_pass0 & SEEN_DATAREF) {
 				if (offsetof(struct sk_buff, len) <= 127)
 					/* mov    off8(%rdi),%r9d */
 					EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
@@ -260,9 +261,14 @@ void bpf_jit_compile(struct sk_filter *fp)
 			case BPF_S_ALU_DIV_X: /* A /= X; */
 				seen |= SEEN_XREG;
 				EMIT2(0x85, 0xdb);	/* test %ebx,%ebx */
-				if (pc_ret0 != -1)
-					EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
-				else {
+				if (pc_ret0 > 0) {
+					/* addrs[pc_ret0 - 1] is start address of target
+					 * (addrs[i] - 4) is the address following this jmp
+					 * ("xor %edx,%edx; div %ebx" being 4 bytes long)
+					 */
+					EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
+								(addrs[i] - 4));
+				} else {
 					EMIT_COND_JMP(X86_JNE, 2 + 5);
 					CLEAR_A();
 					EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
@@ -335,12 +341,12 @@ void bpf_jit_compile(struct sk_filter *fp)
 				}
 				/* fallinto */
 			case BPF_S_RET_A:
-				if (seen) {
+				if (seen_or_pass0) {
 					if (i != flen - 1) {
 						EMIT_JMP(cleanup_addr - addrs[i]);
 						break;
 					}
-					if (seen & SEEN_XREG)
+					if (seen_or_pass0 & SEEN_XREG)
 						EMIT4(0x48, 0x8b, 0x5d, 0xf8);  /* mov  -8(%rbp),%rbx */
 					EMIT1(0xc9);		/* leaveq */
 				}
@@ -483,8 +489,9 @@ common_load:			seen |= SEEN_DATAREF;
 				goto common_load;
 			case BPF_S_LDX_B_MSH:
 				if ((int)K < 0) {
-					if (pc_ret0 != -1) {
-						EMIT_JMP(addrs[pc_ret0] - addrs[i]);
+					if (pc_ret0 > 0) {
+						/* addrs[pc_ret0 - 1] is the start address */
+						EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]);
 						break;
 					}
 					CLEAR_A();
@@ -599,13 +606,14 @@ cond_branch:			f_offset = addrs[i + filter[i].jf] - addrs[i];
 		 * use it to give the cleanup instruction(s) addr
 		 */
 		cleanup_addr = proglen - 1; /* ret */
-		if (seen)
+		if (seen_or_pass0)
 			cleanup_addr -= 1; /* leaveq */
-		if (seen & SEEN_XREG)
+		if (seen_or_pass0 & SEEN_XREG)
 			cleanup_addr -= 4; /* mov  -8(%rbp),%rbx */
 
 		if (image) {
-			WARN_ON(proglen != oldproglen);
+			if (proglen != oldproglen)
+				pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen);
 			break;
 		}
 		if (proglen == oldproglen) {
diff --git a/arch/x86/platform/geode/Makefile b/arch/x86/platform/geode/Makefile
index 07c9cd0..d8ba564 100644
--- a/arch/x86/platform/geode/Makefile
+++ b/arch/x86/platform/geode/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_ALIX)		+= alix.o
+obj-$(CONFIG_GEOS)		+= geos.o
diff --git a/arch/x86/platform/geode/geos.c b/arch/x86/platform/geode/geos.c
new file mode 100644
index 0000000..c2e6d53
--- /dev/null
+++ b/arch/x86/platform/geode/geos.c
@@ -0,0 +1,128 @@
+/*
+ * System Specific setup for Traverse Technologies GEOS.
+ * At the moment this means setup of GPIO control of LEDs.
+ *
+ * Copyright (C) 2008 Constantin Baranov <const@mimas.ru>
+ * Copyright (C) 2011 Ed Wildgoose <kernel@wildgooses.com>
+ *                and Philip Prindeville <philipp@redfish-solutions.com>
+ *
+ * TODO: There are large similarities with leds-net5501.c
+ * by Alessandro Zummo <a.zummo@towertech.it>
+ * In the future leds-net5501.c should be migrated over to platform
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/dmi.h>
+
+#include <asm/geode.h>
+
+static struct gpio_keys_button geos_gpio_buttons[] = {
+	{
+		.code = KEY_RESTART,
+		.gpio = 3,
+		.active_low = 1,
+		.desc = "Reset button",
+		.type = EV_KEY,
+		.wakeup = 0,
+		.debounce_interval = 100,
+		.can_disable = 0,
+	}
+};
+static struct gpio_keys_platform_data geos_buttons_data = {
+	.buttons = geos_gpio_buttons,
+	.nbuttons = ARRAY_SIZE(geos_gpio_buttons),
+	.poll_interval = 20,
+};
+
+static struct platform_device geos_buttons_dev = {
+	.name = "gpio-keys-polled",
+	.id = 1,
+	.dev = {
+		.platform_data = &geos_buttons_data,
+	}
+};
+
+static struct gpio_led geos_leds[] = {
+	{
+		.name = "geos:1",
+		.gpio = 6,
+		.default_trigger = "default-on",
+		.active_low = 1,
+	},
+	{
+		.name = "geos:2",
+		.gpio = 25,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+	{
+		.name = "geos:3",
+		.gpio = 27,
+		.default_trigger = "default-off",
+		.active_low = 1,
+	},
+};
+
+static struct gpio_led_platform_data geos_leds_data = {
+	.num_leds = ARRAY_SIZE(geos_leds),
+	.leds = geos_leds,
+};
+
+static struct platform_device geos_leds_dev = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev.platform_data = &geos_leds_data,
+};
+
+static struct __initdata platform_device *geos_devs[] = {
+	&geos_buttons_dev,
+	&geos_leds_dev,
+};
+
+static void __init register_geos(void)
+{
+	/* Setup LED control through leds-gpio driver */
+	platform_add_devices(geos_devs, ARRAY_SIZE(geos_devs));
+}
+
+static int __init geos_init(void)
+{
+	const char *vendor, *product;
+
+	if (!is_geode())
+		return 0;
+
+	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+	if (!vendor || strcmp(vendor, "Traverse Technologies"))
+		return 0;
+
+	product = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!product || strcmp(product, "Geos"))
+		return 0;
+
+	printk(KERN_INFO "%s: system is recognized as \"%s %s\"\n",
+	       KBUILD_MODNAME, vendor, product);
+
+	register_geos();
+
+	return 0;
+}
+
+module_init(geos_init);
+
+MODULE_AUTHOR("Philip Prindeville <philipp@redfish-solutions.com>");
+MODULE_DESCRIPTION("Traverse Technologies Geos System Setup");
+MODULE_LICENSE("GPL");
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
index 5917eb5..e6cb80f 100644
--- a/arch/x86/platform/iris/iris.c
+++ b/arch/x86/platform/iris/iris.c
@@ -23,6 +23,7 @@
 
 #include <linux/moduleparam.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
@@ -62,29 +63,75 @@ static void iris_power_off(void)
  * by reading its input port and seeing whether the read value is
  * meaningful.
  */
-static int iris_init(void)
+static int iris_probe(struct platform_device *pdev)
 {
-	unsigned char status;
-	if (force != 1) {
-		printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n");
-		return -ENODEV;
-	}
-	status = inb(IRIS_GIO_INPUT);
+	unsigned char status = inb(IRIS_GIO_INPUT);
 	if (status == IRIS_GIO_NODEV) {
-		printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n");
+		printk(KERN_ERR "This machine does not seem to be an Iris. "
+			"Power off handler not installed.\n");
 		return -ENODEV;
 	}
 	old_pm_power_off = pm_power_off;
 	pm_power_off = &iris_power_off;
 	printk(KERN_INFO "Iris power_off handler installed.\n");
-
 	return 0;
 }
 
-static void iris_exit(void)
+static int iris_remove(struct platform_device *pdev)
 {
 	pm_power_off = old_pm_power_off;
 	printk(KERN_INFO "Iris power_off handler uninstalled.\n");
+	return 0;
+}
+
+static struct platform_driver iris_driver = {
+	.driver		= {
+		.name   = "iris",
+		.owner  = THIS_MODULE,
+	},
+	.probe          = iris_probe,
+	.remove         = iris_remove,
+};
+
+static struct resource iris_resources[] = {
+	{
+		.start  = IRIS_GIO_BASE,
+		.end    = IRIS_GIO_OUTPUT,
+		.flags  = IORESOURCE_IO,
+		.name   = "address"
+	}
+};
+
+static struct platform_device *iris_device;
+
+static int iris_init(void)
+{
+	int ret;
+	if (force != 1) {
+		printk(KERN_ERR "The force parameter has not been set to 1."
+			" The Iris poweroff handler will not be installed.\n");
+		return -ENODEV;
+	}
+	ret = platform_driver_register(&iris_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Failed to register iris platform driver: %d\n",
+			ret);
+		return ret;
+	}
+	iris_device = platform_device_register_simple("iris", (-1),
+				iris_resources, ARRAY_SIZE(iris_resources));
+	if (IS_ERR(iris_device)) {
+		printk(KERN_ERR "Failed to register iris platform device\n");
+		platform_driver_unregister(&iris_driver);
+		return PTR_ERR(iris_device);
+	}
+	return 0;
+}
+
+static void iris_exit(void)
+{
+	platform_device_unregister(iris_device);
+	platform_driver_unregister(&iris_driver);
 }
 
 module_init(iris_init);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
index 2b235b7..e1869b4 100644
--- a/arch/x86/platform/olpc/olpc-xo15-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -24,6 +24,62 @@
 #define XO15_SCI_DEVICE_NAME		"OLPC XO-1.5 SCI"
 
 static unsigned long xo15_sci_gpe;
+static bool lid_wake_on_close;
+
+/*
+ * The normal ACPI LID wakeup behavior is wake-on-open, but not
+ * wake-on-close. This is implemented as standard by the XO-1.5 DSDT.
+ *
+ * We provide here a sysfs attribute that will additionally enable
+ * wake-on-close behavior. This is useful (e.g.) when we oportunistically
+ * suspend with the display running; if the lid is then closed, we want to
+ * wake up to turn the display off.
+ *
+ * This is controlled through a custom method in the XO-1.5 DSDT.
+ */
+static int set_lid_wake_behavior(bool wake_on_close)
+{
+	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 = wake_on_close;
+	status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list,
+				      NULL);
+	if (ACPI_FAILURE(status)) {
+		pr_warning(PFX "failed to set lid behavior\n");
+		return 1;
+	}
+
+	lid_wake_on_close = wake_on_close;
+	return 0;
+}
+
+static ssize_t lid_wake_on_close_show(struct kobject *s,
+				      struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", lid_wake_on_close);
+}
+
+static ssize_t lid_wake_on_close_store(struct kobject *s,
+				       struct kobj_attribute *attr,
+				       const char *buf, size_t n)
+{
+	unsigned int val;
+
+	if (sscanf(buf, "%u", &val) != 1)
+		return -EINVAL;
+
+	set_lid_wake_behavior(!!val);
+	return n;
+}
+
+static struct kobj_attribute lid_wake_on_close_attr =
+	__ATTR(lid_wake_on_close, 0644,
+	       lid_wake_on_close_show, lid_wake_on_close_store);
 
 static void battery_status_changed(void)
 {
@@ -91,6 +147,7 @@ static int xo15_sci_add(struct acpi_device *device)
 {
 	unsigned long long tmp;
 	acpi_status status;
+	int r;
 
 	if (!device)
 		return -EINVAL;
@@ -112,6 +169,10 @@ static int xo15_sci_add(struct acpi_device *device)
 
 	dev_info(&device->dev, "Initialized, GPE = 0x%lx\n", xo15_sci_gpe);
 
+	r = sysfs_create_file(&device->dev.kobj, &lid_wake_on_close_attr.attr);
+	if (r)
+		goto err_sysfs;
+
 	/* Flush queue, and enable all SCI events */
 	process_sci_queue();
 	olpc_ec_mask_write(EC_SCI_SRC_ALL);
@@ -123,6 +184,11 @@ static int xo15_sci_add(struct acpi_device *device)
 		device_init_wakeup(&device->dev, true);
 
 	return 0;
+
+err_sysfs:
+	acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
+	cancel_work_sync(&sci_work);
+	return r;
 }
 
 static int xo15_sci_remove(struct acpi_device *device, int type)
@@ -130,6 +196,7 @@ static int xo15_sci_remove(struct acpi_device *device, int type)
 	acpi_disable_gpe(NULL, xo15_sci_gpe);
 	acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
 	cancel_work_sync(&sci_work);
+	sysfs_remove_file(&device->dev.kobj, &lid_wake_on_close_attr.attr);
 	return 0;
 }
 
diff --git a/arch/x86/platform/olpc/olpc.c b/arch/x86/platform/olpc/olpc.c
index 7cce722..8260747 100644
--- a/arch/x86/platform/olpc/olpc.c
+++ b/arch/x86/platform/olpc/olpc.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/syscore_ops.h>
+#include <linux/debugfs.h>
 
 #include <asm/geode.h>
 #include <asm/setup.h>
@@ -31,6 +32,13 @@ EXPORT_SYMBOL_GPL(olpc_platform_info);
 
 static DEFINE_SPINLOCK(ec_lock);
 
+/* debugfs interface to EC commands */
+#define EC_MAX_CMD_ARGS (5 + 1)	/* cmd byte + 5 args */
+#define EC_MAX_CMD_REPLY (8)
+static struct dentry *ec_debugfs_dir;
+static unsigned char ec_debugfs_resp[EC_MAX_CMD_REPLY];
+static unsigned int ec_debugfs_resp_bytes;
+
 /* EC event mask to be applied during suspend (defining wakeup sources). */
 static u16 ec_wakeup_mask;
 
@@ -269,6 +277,83 @@ int olpc_ec_sci_query(u16 *sci_value)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
 
+static ssize_t ec_gen_write(struct file *file, const char __user *buf,
+			    size_t size, loff_t *ppos)
+{
+	int i, m;
+	unsigned char ec_cmd[EC_MAX_CMD_ARGS];
+	unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
+	char cmdbuf[64];
+	int ec_cmd_bytes;
+
+	size = simple_write_to_buffer(cmdbuf, sizeof(cmdbuf), ppos, buf, size);
+
+	m = sscanf(cmdbuf, "%x:%u %x %x %x %x %x", &ec_cmd_int[0],
+		   &ec_debugfs_resp_bytes,
+		   &ec_cmd_int[1], &ec_cmd_int[2], &ec_cmd_int[3],
+		   &ec_cmd_int[4], &ec_cmd_int[5]);
+	if (m < 2 || ec_debugfs_resp_bytes > EC_MAX_CMD_REPLY) {
+		printk(KERN_DEBUG "olpc-ec: bad ec cmd:  "
+		       "cmd:response-count [arg1 [arg2 ...]]\n");
+		return -EINVAL;
+	}
+
+	/* convert scanf'd ints to char */
+	ec_cmd_bytes = m - 2;
+	for (i = 0; i <= ec_cmd_bytes; i++)
+		ec_cmd[i] = ec_cmd_int[i];
+
+	printk(KERN_DEBUG "olpc-ec: debugfs cmd 0x%02x with %d args "
+	       "%02x %02x %02x %02x %02x, want %d returns\n",
+	       ec_cmd[0], ec_cmd_bytes, ec_cmd[1], ec_cmd[2], ec_cmd[3],
+	       ec_cmd[4], ec_cmd[5], ec_debugfs_resp_bytes);
+
+	olpc_ec_cmd((unsigned char) ec_cmd[0],
+		(ec_cmd_bytes == 0) ? NULL : &ec_cmd[1],
+		ec_cmd_bytes, ec_debugfs_resp, ec_debugfs_resp_bytes);
+
+	printk(KERN_DEBUG "olpc-ec: response "
+	       "%02x %02x %02x %02x %02x %02x %02x %02x (%d bytes expected)\n",
+	       ec_debugfs_resp[0], ec_debugfs_resp[1], ec_debugfs_resp[2],
+	       ec_debugfs_resp[3], ec_debugfs_resp[4], ec_debugfs_resp[5],
+	       ec_debugfs_resp[6], ec_debugfs_resp[7], ec_debugfs_resp_bytes);
+
+	return size;
+}
+
+static ssize_t ec_gen_read(struct file *file, char __user *buf,
+			   size_t size, loff_t *ppos)
+{
+	unsigned int i, r;
+	char *rp;
+	char respbuf[64];
+
+	rp = respbuf;
+	rp += sprintf(rp, "%02x", ec_debugfs_resp[0]);
+	for (i = 1; i < ec_debugfs_resp_bytes; i++)
+		rp += sprintf(rp, ", %02x", ec_debugfs_resp[i]);
+	rp += sprintf(rp, "\n");
+
+	r = rp - respbuf;
+
+	return simple_read_from_buffer(buf, size, ppos, respbuf, r);
+}
+
+static const struct file_operations ec_debugfs_genops = {
+	.write	 = ec_gen_write,
+	.read	 = ec_gen_read,
+};
+
+static void setup_debugfs(void)
+{
+	ec_debugfs_dir = debugfs_create_dir("olpc-ec", 0);
+	if (ec_debugfs_dir == ERR_PTR(-ENODEV))
+		return;
+
+	debugfs_create_file("generic", 0600, ec_debugfs_dir, NULL,
+			    &ec_debugfs_genops);
+}
+
 static int olpc_ec_suspend(void)
 {
 	return olpc_ec_mask_write(ec_wakeup_mask);
@@ -372,6 +457,7 @@ static int __init olpc_init(void)
 	}
 
 	register_syscore_ops(&olpc_syscore_ops);
+	setup_debugfs();
 
 	return 0;
 }
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 12eb07b..312c9e3 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -777,11 +777,11 @@ static DEFINE_PER_CPU(unsigned long, xen_cr0_value);
 
 static unsigned long xen_read_cr0(void)
 {
-	unsigned long cr0 = percpu_read(xen_cr0_value);
+	unsigned long cr0 = this_cpu_read(xen_cr0_value);
 
 	if (unlikely(cr0 == 0)) {
 		cr0 = native_read_cr0();
-		percpu_write(xen_cr0_value, cr0);
+		this_cpu_write(xen_cr0_value, cr0);
 	}
 
 	return cr0;
@@ -791,7 +791,7 @@ static void xen_write_cr0(unsigned long cr0)
 {
 	struct multicall_space mcs;
 
-	percpu_write(xen_cr0_value, cr0);
+	this_cpu_write(xen_cr0_value, cr0);
 
 	/* Only pay attention to cr0.TS; everything else is
 	   ignored. */
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 8bbb465..1573376 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -26,7 +26,7 @@ static unsigned long xen_save_fl(void)
 	struct vcpu_info *vcpu;
 	unsigned long flags;
 
-	vcpu = percpu_read(xen_vcpu);
+	vcpu = this_cpu_read(xen_vcpu);
 
 	/* flag has opposite sense of mask */
 	flags = !vcpu->evtchn_upcall_mask;
@@ -50,7 +50,7 @@ static void xen_restore_fl(unsigned long flags)
 	   make sure we're don't switch CPUs between getting the vcpu
 	   pointer and updating the mask. */
 	preempt_disable();
-	vcpu = percpu_read(xen_vcpu);
+	vcpu = this_cpu_read(xen_vcpu);
 	vcpu->evtchn_upcall_mask = flags;
 	preempt_enable_no_resched();
 
@@ -72,7 +72,7 @@ static void xen_irq_disable(void)
 	   make sure we're don't switch CPUs between getting the vcpu
 	   pointer and updating the mask. */
 	preempt_disable();
-	percpu_read(xen_vcpu)->evtchn_upcall_mask = 1;
+	this_cpu_read(xen_vcpu)->evtchn_upcall_mask = 1;
 	preempt_enable_no_resched();
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable);
@@ -86,7 +86,7 @@ static void xen_irq_enable(void)
 	   the caller is confused and is trying to re-enable interrupts
 	   on an indeterminate processor. */
 
-	vcpu = percpu_read(xen_vcpu);
+	vcpu = this_cpu_read(xen_vcpu);
 	vcpu->evtchn_upcall_mask = 0;
 
 	/* Doesn't matter if we get preempted here, because any
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 58a0e46..1a309ee 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1071,14 +1071,14 @@ static void drop_other_mm_ref(void *info)
 	struct mm_struct *mm = info;
 	struct mm_struct *active_mm;
 
-	active_mm = percpu_read(cpu_tlbstate.active_mm);
+	active_mm = this_cpu_read(cpu_tlbstate.active_mm);
 
-	if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK)
+	if (active_mm == mm && this_cpu_read(cpu_tlbstate.state) != TLBSTATE_OK)
 		leave_mm(smp_processor_id());
 
 	/* If this cpu still has a stale cr3 reference, then make sure
 	   it has been flushed. */
-	if (percpu_read(xen_current_cr3) == __pa(mm->pgd))
+	if (this_cpu_read(xen_current_cr3) == __pa(mm->pgd))
 		load_cr3(swapper_pg_dir);
 }
 
@@ -1185,17 +1185,17 @@ static void __init xen_pagetable_setup_done(pgd_t *base)
 
 static void xen_write_cr2(unsigned long cr2)
 {
-	percpu_read(xen_vcpu)->arch.cr2 = cr2;
+	this_cpu_read(xen_vcpu)->arch.cr2 = cr2;
 }
 
 static unsigned long xen_read_cr2(void)
 {
-	return percpu_read(xen_vcpu)->arch.cr2;
+	return this_cpu_read(xen_vcpu)->arch.cr2;
 }
 
 unsigned long xen_read_cr2_direct(void)
 {
-	return percpu_read(xen_vcpu_info.arch.cr2);
+	return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
 static void xen_flush_tlb(void)
@@ -1278,12 +1278,12 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
 
 static unsigned long xen_read_cr3(void)
 {
-	return percpu_read(xen_cr3);
+	return this_cpu_read(xen_cr3);
 }
 
 static void set_current_cr3(void *v)
 {
-	percpu_write(xen_current_cr3, (unsigned long)v);
+	this_cpu_write(xen_current_cr3, (unsigned long)v);
 }
 
 static void __xen_write_cr3(bool kernel, unsigned long cr3)
@@ -1306,7 +1306,7 @@ static void __xen_write_cr3(bool kernel, unsigned long cr3)
 	xen_extend_mmuext_op(&op);
 
 	if (kernel) {
-		percpu_write(xen_cr3, cr3);
+		this_cpu_write(xen_cr3, cr3);
 
 		/* Update xen_current_cr3 once the batch has actually
 		   been submitted. */
@@ -1322,7 +1322,7 @@ static void xen_write_cr3(unsigned long cr3)
 
 	/* Update while interrupts are disabled, so its atomic with
 	   respect to ipis */
-	percpu_write(xen_cr3, cr3);
+	this_cpu_write(xen_cr3, cr3);
 
 	__xen_write_cr3(true, cr3);
 
diff --git a/arch/x86/xen/multicalls.h b/arch/x86/xen/multicalls.h
index dee79b7..9c2e74f 100644
--- a/arch/x86/xen/multicalls.h
+++ b/arch/x86/xen/multicalls.h
@@ -47,7 +47,7 @@ static inline void xen_mc_issue(unsigned mode)
 		xen_mc_flush();
 
 	/* restore flags saved in xen_mc_batch */
-	local_irq_restore(percpu_read(xen_mc_irq_flags));
+	local_irq_restore(this_cpu_read(xen_mc_irq_flags));
 }
 
 /* Set up a callback to be called when the current batch is flushed */
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 041d4fe..449f868 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -76,7 +76,7 @@ static void __cpuinit cpu_bringup(void)
 	xen_setup_cpu_clockevents();
 
 	set_cpu_online(cpu, true);
-	percpu_write(cpu_state, CPU_ONLINE);
+	this_cpu_write(cpu_state, CPU_ONLINE);
 	wmb();
 
 	/* We can take interrupts now: we're officially "up". */
diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h
index dae9a8b..6015371 100644
--- a/arch/xtensa/include/asm/irqflags.h
+++ b/arch/xtensa/include/asm/irqflags.h
@@ -12,6 +12,7 @@
 #define _XTENSA_IRQFLAGS_H
 
 #include <linux/types.h>
+#include <asm/processor.h>
 
 static inline unsigned long arch_local_save_flags(void)
 {
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
index d4baed2..f30b8bc 100644
--- a/arch/xtensa/include/asm/regs.h
+++ b/arch/xtensa/include/asm/regs.h
@@ -25,48 +25,49 @@
 #ifndef _XTENSA_REGS_H
 #define _XTENSA_REGS_H
 
-/*  Special registers.  */
-
-#define LBEG		0
-#define LEND		1
-#define LCOUNT		2
-#define SAR		3
-#define BR		4
-#define SCOMPARE1	12
-#define ACCHI		16
-#define ACCLO		17
-#define MR		32
-#define WINDOWBASE	72
-#define WINDOWSTART	73
-#define PTEVADDR	83
-#define RASID		90
-#define ITLBCFG		91
-#define DTLBCFG		92
-#define IBREAKENABLE	96
-#define DDR		104
-#define IBREAKA		128
-#define DBREAKA		144
-#define DBREAKC		160
-#define EPC		176
-#define EPC_1		177
-#define DEPC		192
-#define EPS		192
-#define EPS_1		193
-#define EXCSAVE		208
-#define EXCSAVE_1	209
-#define INTERRUPT	226
-#define INTENABLE	228
-#define PS		230
-#define THREADPTR	231
-#define EXCCAUSE	232
-#define DEBUGCAUSE	233
-#define CCOUNT		234
-#define PRID		235
-#define ICOUNT		236
-#define ICOUNTLEVEL	237
-#define EXCVADDR	238
-#define CCOMPARE	240
-#define MISC		244
+/* Special register numbers
+ *
+ * LBEG		0
+ * LEND		1
+ * LCOUNT	2
+ * SAR		3
+ * BR		4
+ * SCOMPARE1	12
+ * ACCHI	16
+ * ACCLO	17
+ * MR		32
+ * WINDOWBASE	72
+ * WINDOWSTART	73
+ * PTEVADDR	83
+ * RASID	90
+ * ITLBCFG	91
+ * DTLBCFG	92
+ * IBREAKENABLE	96
+ * DDR		104
+ * IBREAKA	128
+ * DBREAKA	144
+ * DBREAKC	160
+ * EPC		176
+ * EPC1		177
+ * DEPC		192
+ * EPS		192
+ * EPS1		193
+ * EXCSAVE	208
+ * EXCSAVE1	209
+ * INTERRUPT	226
+ * INTENABLE	228
+ * PS		230
+ * THREADPTR	231
+ * EXCCAUSE	232
+ * DEBUGCAUSE	233
+ * CCOUNT	234
+ * PRID		235
+ * ICOUNT	236
+ * ICOUNTLEVEL	237
+ * EXCVADDR	238
+ * CCOMPARE	240
+ * MISC		244
+ */
 
 /*  Special names for read-only and write-only interrupt registers.  */
 
@@ -74,6 +75,12 @@
 #define INTSET		226
 #define INTCLEAR	227
 
+#define XTREG_EPS(x)		(192+(x))
+#define XTREG_EPC(x)		(176+(x))
+#define XTREG_EXCSAVE(x)	(208+(x))
+#define XTREG_CCOMPARE(x)	(240+(x))
+#define XTREG_DBREAKC(x)	(160+(x))
+
 /*  EXCCAUSE register fields  */
 
 #define EXCCAUSE_EXCCAUSE_SHIFT	0
diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h
index 053bc42..5ec20e1 100644
--- a/arch/xtensa/include/asm/timex.h
+++ b/arch/xtensa/include/asm/timex.h
@@ -65,8 +65,8 @@ extern cycles_t cacheflush_time;
 
 #define WSR_CCOUNT(r)	  asm volatile ("wsr %0,"__stringify(CCOUNT) :: "a" (r))
 #define RSR_CCOUNT(r)	  asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (r))
-#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r))
-#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r))
+#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(XTREG_CCOMPARE(x)) :: "a"(r))
+#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(XTREG_CCOMPARE(x)) : "=a"(r))
 
 static inline unsigned long get_ccount (void)
 {
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h
index 3fa526f..c957576 100644
--- a/arch/xtensa/include/asm/uaccess.h
+++ b/arch/xtensa/include/asm/uaccess.h
@@ -17,7 +17,6 @@
 #define _XTENSA_UACCESS_H
 
 #include <linux/errno.h>
-#include <linux/prefetch.h>
 #include <asm/types.h>
 
 #define VERIFY_READ    0
@@ -158,6 +157,7 @@
 #else /* __ASSEMBLY__ not defined */
 
 #include <linux/sched.h>
+#include <linux/prefetch.h>
 
 /*
  * The fs value determines whether argument validity checking should
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
index 33d6e9d..26bf883 100644
--- a/arch/xtensa/kernel/align.S
+++ b/arch/xtensa/kernel/align.S
@@ -148,7 +148,7 @@
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -171,7 +171,7 @@ ENTRY(fast_unaligned)
 	s32i	a8, a2, PT_AREG8
 
 	rsr	a0, DEPC
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	s32i	a0, a2, PT_AREG2
 	s32i	a3, a2, PT_AREG3
 
@@ -184,7 +184,7 @@ ENTRY(fast_unaligned)
 	 *
 	 * The only possible danger of a double exception on the
 	 * following l32i instructions is kernel code in vmalloc
-	 * memory. The processor was just executing at the EPC_1
+	 * memory. The processor was just executing at the EPC1
 	 * address, and indeed, already fetched the instruction.  That
 	 * guarantees a TLB mapping, which hasn't been replaced by
 	 * this unaligned exception handler that uses only static TLB
@@ -197,7 +197,7 @@ ENTRY(fast_unaligned)
 
 	/* Extract the instruction that caused the unaligned access. */
 
-	rsr	a7, EPC_1	# load exception address
+	rsr	a7, EPC1	# load exception address
 	movi	a3, ~3
 	and	a3, a3, a7	# mask lower bits
 
@@ -284,7 +284,7 @@ ENTRY(fast_unaligned)
 	wsr	a5, LCOUNT
 #endif
 
-1:	wsr	a7, EPC_1		# skip load instruction
+1:	wsr	a7, EPC1		# skip load instruction
 	extui	a4, a4, INSN_T, 4	# extract target register
 	movi	a5, .Lload_table
 	addx8	a4, a4, a5
@@ -364,7 +364,7 @@ ENTRY(fast_unaligned)
 	wsr	a4, LCOUNT
 #endif
 
-1:	wsr	a7, EPC_1		# skip store instruction
+1:	wsr	a7, EPC1		# skip store instruction
 	movi	a4, ~3
 	and	a4, a4, a8		# align memory address
 
@@ -406,7 +406,7 @@ ENTRY(fast_unaligned)
 
 .Lexit:
 	movi	a4, 0
-	rsr	a3, EXCSAVE_1
+	rsr	a3, EXCSAVE1
 	s32i	a4, a3, EXC_TABLE_FIXUP
 
 	/* Restore working register */
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
index 2bc1e14..095082f 100644
--- a/arch/xtensa/kernel/coprocessor.S
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -34,7 +34,7 @@
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -43,7 +43,7 @@
 /* IO protection is currently unsupported. */
 
 ENTRY(fast_io_protect)
-	wsr	a0, EXCSAVE_1
+	wsr	a0, EXCSAVE1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
@@ -213,14 +213,14 @@ ENTRY(coprocessor_restore)
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
  */
 
 ENTRY(fast_coprocessor_double)
-	wsr	a0, EXCSAVE_1
+	wsr	a0, EXCSAVE1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
@@ -229,7 +229,7 @@ ENTRY(fast_coprocessor)
 
 	/* Save remaining registers a1-a3 and SAR */
 
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	s32i	a3, a2, PT_AREG3
 	rsr	a3, SAR
 	s32i	a1, a2, PT_AREG1
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 6223f33..b0d23a1 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -110,9 +110,9 @@
 
 ENTRY(user_exception)
 
-	/* Save a2, a3, and depc, restore excsave_1 and set SP. */
+	/* Save a2, a3, and depc, restore excsave1 and set SP. */
 
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	rsr	a0, DEPC
 	s32i	a1, a2, PT_AREG1
 	s32i	a0, a2, PT_AREG2
@@ -234,7 +234,7 @@ _user_exception:
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -252,7 +252,7 @@ ENTRY(kernel_exception)
 
 	/* Save a0, a2, a3, DEPC and set SP. */
 
-	xsr	a3, EXCSAVE_1		# restore a3, excsave_1
+	xsr	a3, EXCSAVE1		# restore a3, excsave1
 	rsr	a0, DEPC		# get a2
 	s32i	a1, a2, PT_AREG1
 	s32i	a0, a2, PT_AREG2
@@ -324,7 +324,7 @@ common_exception:
 	/* Save some registers, disable loops and clear the syscall flag. */
 
 	rsr	a2, DEBUGCAUSE
-	rsr	a3, EPC_1
+	rsr	a3, EPC1
 	s32i	a2, a1, PT_DEBUGCAUSE
 	s32i	a3, a1, PT_PC
 
@@ -340,7 +340,7 @@ common_exception:
 
 	rsr	a0, EXCCAUSE
 	movi	a3, 0
-	rsr	a2, EXCSAVE_1
+	rsr	a2, EXCSAVE1
 	s32i	a0, a1, PT_EXCCAUSE
 	s32i	a3, a2, EXC_TABLE_FIXUP
 
@@ -604,7 +604,7 @@ common_exception_exit:
 
 1:	l32i	a2, a1, PT_PC
 	l32i	a3, a1, PT_SAR
-	wsr	a2, EPC_1
+	wsr	a2, EPC1
 	wsr	a3, SAR
 
 	/* Restore LBEG, LEND, LCOUNT */
@@ -651,14 +651,14 @@ common_exception_exit:
 
 ENTRY(debug_exception)
 
-	rsr	a0, EPS + XCHAL_DEBUGLEVEL
+	rsr	a0, XTREG_EPS(XCHAL_DEBUGLEVEL)
 	bbsi.l	a0, PS_EXCM_BIT, 1f	# exception mode
 
-	/* Set EPC_1 and EXCCAUSE */
+	/* Set EPC1 and EXCCAUSE */
 
 	wsr	a2, DEPC		# save a2 temporarily
-	rsr	a2, EPC + XCHAL_DEBUGLEVEL
-	wsr	a2, EPC_1
+	rsr	a2, XTREG_EPC(XCHAL_DEBUGLEVEL)
+	wsr	a2, EPC1
 
 	movi	a2, EXCCAUSE_MAPPED_DEBUG
 	wsr	a2, EXCCAUSE
@@ -669,7 +669,7 @@ ENTRY(debug_exception)
 	or	a2, a0, a2
 	movi	a0, debug_exception	# restore a3, debug jump vector
 	wsr	a2, PS
-	xsr	a0, EXCSAVE + XCHAL_DEBUGLEVEL
+	xsr	a0, XTREG_EXCSAVE(XCHAL_DEBUGLEVEL)
 
 	/* Switch to kernel/user stack, restore jump vector, and save a0 */
 
@@ -686,7 +686,7 @@ ENTRY(debug_exception)
 	mov	a1, a2
 	j	_kernel_exception
 
-2:	rsr	a2, EXCSAVE_1
+2:	rsr	a2, EXCSAVE1
 	l32i	a2, a2, EXC_TABLE_KSTK	# load kernel stack pointer
 	s32i	a0, a2, PT_AREG0
 	movi	a0, 0
@@ -772,7 +772,7 @@ ENTRY(unrecoverable_exception)
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -802,10 +802,10 @@ ENTRY(fast_alloca)
 	movi	a0, 0
 	s32i	a0, a3, EXC_TABLE_FIXUP
 
-	/* Restore a3, excsave_1 */
+	/* Restore a3, excsave1 */
 
-	xsr	a3, EXCSAVE_1		# make sure excsave_1 is valid for dbl.
-	rsr	a4, EPC_1		# get exception address
+	xsr	a3, EXCSAVE1		# make sure excsave1 is valid for dbl.
+	rsr	a4, EPC1		# get exception address
 	s32i	a3, a2, PT_AREG3	# save a3 to stack
 
 #ifdef ALLOCA_EXCEPTION_IN_IRAM
@@ -820,7 +820,7 @@ ENTRY(fast_alloca)
 	jx	a3
 
 .Lunhandled_double:
-	wsr	a0, EXCSAVE_1
+	wsr	a0, EXCSAVE1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
@@ -852,7 +852,7 @@ ENTRY(fast_alloca)
 #endif
 	addi	a4, a4, 3		# step over movsp
 	_EXTUI_MOVSP_DST(a0)		# extract destination register
-	wsr	a4, EPC_1		# save new epc_1
+	wsr	a4, EPC1		# save new epc1
 
 	_bnei	a0, 1, 1f		# no 'movsp a1, ax': jump
 
@@ -946,16 +946,16 @@ ENTRY(fast_alloca)
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  */
 
 ENTRY(fast_syscall_kernel)
 
 	/* Skip syscall. */
 
-	rsr	a0, EPC_1
+	rsr	a0, EPC1
 	addi	a0, a0, 3
-	wsr	a0, EPC_1
+	wsr	a0, EPC1
 
 	l32i	a0, a2, PT_DEPC
 	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
@@ -970,9 +970,9 @@ ENTRY(fast_syscall_user)
 
 	/* Skip syscall. */
 
-	rsr	a0, EPC_1
+	rsr	a0, EPC1
 	addi	a0, a0, 3
-	wsr	a0, EPC_1
+	wsr	a0, EPC1
 
 	l32i	a0, a2, PT_DEPC
 	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
@@ -989,9 +989,9 @@ ENTRY(fast_syscall_unrecoverable)
 
         l32i    a0, a2, PT_AREG0        # restore a0
         xsr     a2, DEPC                # restore a2, depc
-        rsr     a3, EXCSAVE_1
+        rsr     a3, EXCSAVE1
 
-        wsr     a0, EXCSAVE_1
+        wsr     a0, EXCSAVE1
         movi    a0, unrecoverable_exception
         callx0  a0
 
@@ -1011,10 +1011,10 @@ ENTRY(fast_syscall_unrecoverable)
  *   a0:	a2 (syscall-nr), original value saved on stack (PT_AREG0)
  *   a1:	a1
  *   a2:	new stack pointer, original in a0 and DEPC
- *   a3:	dispatch table, original in excsave_1
+ *   a3:	dispatch table, original in excsave1
  *   a4..a15:	unchanged
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1047,7 +1047,7 @@ ENTRY(fast_syscall_unrecoverable)
 
 ENTRY(fast_syscall_xtensa)
 
-	xsr	a3, EXCSAVE_1		# restore a3, excsave1
+	xsr	a3, EXCSAVE1		# restore a3, excsave1
 
 	s32i	a7, a2, PT_AREG7	# we need an additional register
 	movi	a7, 4			# sizeof(unsigned int)
@@ -1113,7 +1113,7 @@ CATCH
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
  */
@@ -1130,7 +1130,7 @@ ENTRY(fast_syscall_spill_registers)
 	/* Save a3 and SAR on stack. */
 
 	rsr	a0, SAR
-	xsr	a3, EXCSAVE_1		# restore a3 and excsave_1
+	xsr	a3, EXCSAVE1		# restore a3 and excsave1
 	s32i	a3, a2, PT_AREG3
 	s32i	a4, a2, PT_AREG4
 	s32i	a0, a2, PT_AREG5	# store SAR to PT_AREG5
@@ -1182,7 +1182,7 @@ fast_syscall_spill_registers_fixup:
 	 * in WS, so that the exception handlers save them to the task stack.
 	 */
 
-	rsr	a3, EXCSAVE_1	# get spill-mask
+	rsr	a3, EXCSAVE1	# get spill-mask
 	slli	a2, a3, 1	# shift left by one
 
 	slli	a3, a2, 32-WSBITS
@@ -1196,9 +1196,9 @@ fast_syscall_spill_registers_fixup:
 	/* Return to the original (user task) WINDOWBASE.
 	 * We leave the following frame behind:
 	 * a0, a1, a2	same
-	 * a3:		trashed (saved in excsave_1)
+	 * a3:		trashed (saved in excsave1)
 	 * depc:	depc (we have to return to that address)
-	 * excsave_1:	a3
+	 * excsave1:	a3
 	 */
 
 	wsr	a3, WINDOWBASE
@@ -1208,7 +1208,7 @@ fast_syscall_spill_registers_fixup:
 	 *  a0: return address
 	 *  a1: used, stack pointer
 	 *  a2: kernel stack pointer
-	 *  a3: available, saved in EXCSAVE_1
+	 *  a3: available, saved in EXCSAVE1
 	 *  depc: exception address
 	 *  excsave: a3
 	 * Note: This frame might be the same as above.
@@ -1240,7 +1240,7 @@ fast_syscall_spill_registers_fixup_return:
 
 	/* Restore fixup handler. */
 
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	movi	a2, fast_syscall_spill_registers_fixup
 	s32i	a2, a3, EXC_TABLE_FIXUP
 	rsr	a2, WINDOWBASE
@@ -1257,7 +1257,7 @@ fast_syscall_spill_registers_fixup_return:
 	/* Restore a3 and return. */
 
 	movi	a3, exc_table
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 
 	rfde
 
@@ -1447,7 +1447,7 @@ ENTRY(_spill_registers)
 
 	movi	a3, exc_table
 	l32i	a1, a3, EXC_TABLE_KSTK
-	wsr	a3, EXCSAVE_1
+	wsr	a3, EXCSAVE1
 
 	movi	a4, (1 << PS_WOE_BIT) | 1
 	wsr	a4, PS
@@ -1459,7 +1459,7 @@ ENTRY(_spill_registers)
 
 1:	/* Kernel space: PANIC! */
 
-	wsr	a0, EXCSAVE_1
+	wsr	a0, EXCSAVE1
 	movi	a0, unrecoverable_exception
 	callx0	a0		# should not return
 1:	j	1b
@@ -1489,7 +1489,7 @@ ENTRY(fast_second_level_miss_double_kernel)
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1583,7 +1583,7 @@ ENTRY(fast_second_level_miss)
 	l32i	a0, a2, PT_AREG0
 	l32i	a1, a2, PT_AREG1
 	l32i	a2, a2, PT_DEPC
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 
 	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
@@ -1618,7 +1618,7 @@ ENTRY(fast_second_level_miss)
 	/* Make sure the exception originated in the special functions */
 
 	movi	a0, __tlbtemp_mapping_start
-	rsr	a3, EPC_1
+	rsr	a3, EPC1
 	bltu	a3, a0, 2f
 	movi	a0, __tlbtemp_mapping_end
 	bgeu	a3, a0, 2f
@@ -1635,7 +1635,7 @@ ENTRY(fast_second_level_miss)
 	/* Check if we have to restore an ITLB mapping. */
 
 	movi	a1, __tlbtemp_mapping_itlb
-	rsr	a3, EPC_1
+	rsr	a3, EPC1
 	sub	a3, a3, a1
 
 	/* Calculate VPN */
@@ -1672,7 +1672,7 @@ ENTRY(fast_second_level_miss)
 
 	movi	a3, exc_table
 	rsr	a1, DEPC
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	s32i	a1, a2, PT_AREG2
 	s32i	a3, a2, PT_AREG3
 	mov	a1, a2
@@ -1695,7 +1695,7 @@ ENTRY(fast_second_level_miss)
  *   a2:	new stack pointer, original in DEPC
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
  *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
@@ -1749,7 +1749,7 @@ ENTRY(fast_store_prohibited)
 
 	/* Restore excsave1 and a3. */
 
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
 	rsr	a2, DEPC
@@ -1767,7 +1767,7 @@ ENTRY(fast_store_prohibited)
 2:	/* If there was a problem, handle fault in C */
 
 	rsr	a4, DEPC	# still holds a2
-	xsr	a3, EXCSAVE_1
+	xsr	a3, EXCSAVE1
 	s32i	a4, a2, PT_AREG2
 	s32i	a3, a2, PT_AREG3
 	l32i	a4, a2, PT_AREG4
@@ -1902,7 +1902,7 @@ ENTRY(_switch_to)
 
 	movi	a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
 	xsr	a14, PS
-	rsr	a3, EXCSAVE_1
+	rsr	a3, EXCSAVE1
 	rsync
 	s32i	a3, a3, EXC_TABLE_FIXUP	/* enter critical section */
 
@@ -1924,7 +1924,7 @@ ENTRY(_switch_to)
 	 *       we return from kernel space.
 	 */
 
-	rsr	a3, EXCSAVE_1		# exc_table
+	rsr	a3, EXCSAVE1		# exc_table
 	movi	a6, 0
 	addi	a7, a5, PT_REGS_OFFSET
 	s32i	a6, a3, EXC_TABLE_FIXUP
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
index 3ef91a7..68648c3 100644
--- a/arch/xtensa/kernel/head.S
+++ b/arch/xtensa/kernel/head.S
@@ -63,9 +63,9 @@ _startup:
 	movi	a0, LOCKLEVEL
 	wsr	a0, PS
 
-	/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
+	/* Preserve the pointer to the boot parameter list in EXCSAVE1 */
 
-	wsr	a2, EXCSAVE_1
+	wsr	a2, EXCSAVE1
 
 	/* Start with a fresh windowbase and windowstart.  */
 
@@ -89,7 +89,7 @@ _startup:
 
 	.set	_index, 0
 	.rept	XCHAL_NUM_DBREAK - 1
-	wsr	a0, DBREAKC + _index
+	wsr	a0, XTREG_DBREAKC(_index)
 	.set	_index, _index + 1
 	.endr
 #endif
@@ -108,7 +108,7 @@ _startup:
 
 	.set	_index, 0
 	.rept	XCHAL_NUM_TIMERS - 1
-	wsr	a0, CCOMPARE + _index
+	wsr	a0, XTREG_CCOMPARE(_index)
 	.set	_index, _index + 1
 	.endr
 
@@ -212,12 +212,12 @@ _startup:
 	/* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
 
 	movi	a2, debug_exception
-	wsr	a2, EXCSAVE + XCHAL_DEBUGLEVEL
+	wsr	a2, XTREG_EXCSAVE(XCHAL_DEBUGLEVEL)
 
 	/* Set up EXCSAVE[1] to point to the exc_table. */
 
 	movi	a6, exc_table
-	xsr	a6, EXCSAVE_1
+	xsr	a6, EXCSAVE1
 
 	/* init_arch kick-starts the linux kernel */
 
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 4340ee0..7ddc1af 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -25,6 +25,11 @@
 static unsigned int cached_irq_mask;
 
 atomic_t irq_err_count;
+void ack_bad_irq(unsigned int irq)
+{
+        atomic_inc(&irq_err_count);
+        printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
+}
 
 /*
  * do_IRQ handles all normal device IRQ's (the special
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index e64efac..14e0b40 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -336,10 +336,10 @@ void __init trap_init(void)
 			set_handler (EXC_TABLE_FAST_KERNEL/4 + cause, handler);
 	}
 
-	/* Initialize EXCSAVE_1 to hold the address of the exception table. */
+	/* Initialize EXCSAVE1 to hold the address of the exception table. */
 
 	i = (unsigned long)exc_table;
-	__asm__ __volatile__("wsr  %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
+	__asm__ __volatile__("wsr  %0, EXCSAVE1\n" : : "a" (i));
 }
 
 /*
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 70066e3..5570ccb 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -30,7 +30,7 @@
  *   a2:	new stack pointer, original value in depc
  *   a3:	dispatch table
  *   depc:	a2, original value saved on stack (PT_DEPC)
- *   excsave_1:	a3
+ *   excsave1:	a3
  *
  * The value for PT_DEPC saved to stack also functions as a boolean to
  * indicate that the exception is either a double or a regular exception:
@@ -69,7 +69,7 @@
 
 ENTRY(_UserExceptionVector)
 
-	xsr	a3, EXCSAVE_1		# save a3 and get dispatch table
+	xsr	a3, EXCSAVE1		# save a3 and get dispatch table
 	wsr	a2, DEPC		# save a2
 	l32i	a2, a3, EXC_TABLE_KSTK	# load kernel stack to a2
 	s32i	a0, a2, PT_AREG0	# save a0 to ESF
@@ -93,7 +93,7 @@ ENTRY(_UserExceptionVector)
 
 ENTRY(_KernelExceptionVector)
 
-	xsr	a3, EXCSAVE_1		# save a3, and get dispatch table
+	xsr	a3, EXCSAVE1		# save a3, and get dispatch table
 	wsr	a2, DEPC		# save a2
 	addi	a2, a1, -16-PT_SIZE	# adjust stack pointer
 	s32i	a0, a2, PT_AREG0	# save a0 to ESF
@@ -126,7 +126,7 @@ ENTRY(_KernelExceptionVector)
  * processing occurs. Also in kernel mode, TLB misses can occur if accessing
  * vmalloc memory, possibly requiring repair in a double exception handler.
  *
- * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as
+ * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE1 doubles as
  * a boolean variable and a pointer to a fixup routine. If the variable
  * EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of
  * zero indicates to use the default kernel/user exception handler.
@@ -167,7 +167,7 @@ ENTRY(_KernelExceptionVector)
  *	a2:	   trashed, original value in EXC_TABLE_DOUBLE_A2
  *	a3:	   exctable
  *	depc:	   a0
- *	excsave_1: a3
+ *	excsave1: a3
  *
  *  - When the kernel enters the fixup handler, it still assumes it is in a
  *    critical section, so EXC_TABLE_FIXUP variable is set to exc_table.
@@ -189,7 +189,7 @@ ENTRY(_KernelExceptionVector)
  * All registers a0...a15 are unchanged from the last exception, except:
  *
  *	a0:	   last address before we jumped to the unrecoverable_exception.
- *	excsave_1: a0
+ *	excsave1: a0
  *
  *
  * See the handle_alloca_user and spill_registers routines for example clients.
@@ -205,7 +205,7 @@ ENTRY(_DoubleExceptionVector)
 
 	/* Deliberately destroy excsave (don't assume it's value was valid). */
 
-	wsr	a3, EXCSAVE_1		# save a3
+	wsr	a3, EXCSAVE1		# save a3
 
 	/* Check for kernel double exception (usually fatal). */
 
@@ -254,7 +254,7 @@ ENTRY(_DoubleExceptionVector)
 	xsr	a2, DEPC		# save a2 and get stack pointer
 	s32i	a0, a2, PT_AREG0
 
-	wsr	a3, EXCSAVE_1		# save a3
+	wsr	a3, EXCSAVE1		# save a3
 	movi	a3, exc_table
 
 	rsr	a0, EXCCAUSE
@@ -331,8 +331,8 @@ ENTRY(_DoubleExceptionVector)
 	xsr	a0, DEPC
 
 .Lunrecoverable:
-	rsr	a3, EXCSAVE_1
-	wsr	a0, EXCSAVE_1
+	rsr	a3, EXCSAVE1
+	wsr	a0, EXCSAVE1
 	movi	a0, unrecoverable_exception
 	callx0	a0
 
@@ -349,7 +349,7 @@ ENTRY(_DoubleExceptionVector)
 	.section .DebugInterruptVector.text, "ax"
 
 ENTRY(_DebugInterruptVector)
-	xsr	a0, EXCSAVE + XCHAL_DEBUGLEVEL
+	xsr	a0, XTREG_EXCSAVE(XCHAL_DEBUGLEVEL)
 	jx	a0
 
 
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 88ecea3..6de5ec4 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -113,6 +113,7 @@ SECTIONS
   /* Data section */
 
   _fdata = .;
+  _sdata = .;
   RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE)
   _edata = .;
 
diff --git a/crypto/Kconfig b/crypto/Kconfig
index e6cfe1a..29f4d73 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -308,6 +308,7 @@ comment "Digest"
 config CRYPTO_CRC32C
 	tristate "CRC32c CRC algorithm"
 	select CRYPTO_HASH
+	select CRC32
 	help
 	  Castagnoli, et al Cyclic Redundancy-Check Algorithm.  Used
 	  by iSCSI for header and data digests and by others.
diff --git a/crypto/ahash.c b/crypto/ahash.c
index ac93c99..33bc9b6 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -46,7 +46,7 @@ static int hash_walk_next(struct crypto_hash_walk *walk)
 	unsigned int nbytes = min(walk->entrylen,
 				  ((unsigned int)(PAGE_SIZE)) - offset);
 
-	walk->data = crypto_kmap(walk->pg, 0);
+	walk->data = kmap_atomic(walk->pg);
 	walk->data += offset;
 
 	if (offset & alignmask) {
@@ -93,7 +93,7 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 		return nbytes;
 	}
 
-	crypto_kunmap(walk->data, 0);
+	kunmap_atomic(walk->data);
 	crypto_yield(walk->flags);
 
 	if (err)
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 0d5a90c..361b5e8 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -79,13 +79,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 		/* wait for any prerequisite operations */
 		async_tx_quiesce(&submit->depend_tx);
 
-		dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
-		src_buf = kmap_atomic(src, KM_USER1) + src_offset;
+		dest_buf = kmap_atomic(dest) + dest_offset;
+		src_buf = kmap_atomic(src) + src_offset;
 
 		memcpy(dest_buf, src_buf, len);
 
-		kunmap_atomic(src_buf, KM_USER1);
-		kunmap_atomic(dest_buf, KM_USER0);
+		kunmap_atomic(src_buf);
+		kunmap_atomic(dest_buf);
 
 		async_tx_sync_epilog(submit);
 	}
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 1e61d1a..4dd80c7 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -43,22 +43,22 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
 
 static inline void blkcipher_map_src(struct blkcipher_walk *walk)
 {
-	walk->src.virt.addr = scatterwalk_map(&walk->in, 0);
+	walk->src.virt.addr = scatterwalk_map(&walk->in);
 }
 
 static inline void blkcipher_map_dst(struct blkcipher_walk *walk)
 {
-	walk->dst.virt.addr = scatterwalk_map(&walk->out, 1);
+	walk->dst.virt.addr = scatterwalk_map(&walk->out);
 }
 
 static inline void blkcipher_unmap_src(struct blkcipher_walk *walk)
 {
-	scatterwalk_unmap(walk->src.virt.addr, 0);
+	scatterwalk_unmap(walk->src.virt.addr);
 }
 
 static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk)
 {
-	scatterwalk_unmap(walk->dst.virt.addr, 1);
+	scatterwalk_unmap(walk->dst.virt.addr);
 }
 
 /* Get a spot of the specified length that does not straddle a page.
diff --git a/crypto/ccm.c b/crypto/ccm.c
index c36d654..32fe1bb 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -216,12 +216,12 @@ static void get_data_to_compute(struct crypto_cipher *tfm,
 			scatterwalk_start(&walk, sg_next(walk.sg));
 			n = scatterwalk_clamp(&walk, len);
 		}
-		data_src = scatterwalk_map(&walk, 0);
+		data_src = scatterwalk_map(&walk);
 
 		compute_mac(tfm, data_src, n, pctx);
 		len -= n;
 
-		scatterwalk_unmap(data_src, 0);
+		scatterwalk_unmap(data_src);
 		scatterwalk_advance(&walk, n);
 		scatterwalk_done(&walk, 0, len);
 		if (len)
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index 3f9ad28..06f7018 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/crc32.h>
 
 #define CHKSUM_BLOCK_SIZE	1
 #define CHKSUM_DIGEST_SIZE	4
@@ -53,95 +54,6 @@ struct chksum_desc_ctx {
 };
 
 /*
- * This is the CRC-32C table
- * Generated with:
- * width = 32 bits
- * poly = 0x1EDC6F41
- * reflect input bytes = true
- * reflect output bytes = true
- */
-
-static const u32 crc32c_table[256] = {
-	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
-	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
-	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
-	0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
-	0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
-	0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
-	0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
-	0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
-	0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
-	0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
-	0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
-	0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
-	0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
-	0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
-	0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
-	0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
-	0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
-	0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
-	0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
-	0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
-	0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
-	0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
-	0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
-	0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
-	0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
-	0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
-	0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
-	0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
-	0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
-	0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
-	0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
-	0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
-	0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
-	0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
-	0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
-	0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
-	0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
-	0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
-	0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
-	0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
-	0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
-	0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
-	0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
-	0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
-	0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
-	0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
-	0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
-	0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
-	0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
-	0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
-	0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
-	0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
-	0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
-	0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
-	0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
-	0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
-	0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
-	0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
-	0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
-	0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
-	0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
-	0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
-	0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
-	0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
-};
-
-/*
- * Steps through buffer one byte at at time, calculates reflected
- * crc using table.
- */
-
-static u32 crc32c(u32 crc, const u8 *data, unsigned int length)
-{
-	while (length--)
-		crc = crc32c_table[(crc ^ *data++) & 0xFFL] ^ (crc >> 8);
-
-	return crc;
-}
-
-/*
  * Steps through buffer one byte at at time, calculates reflected
  * crc using table.
  */
@@ -179,7 +91,7 @@ static int chksum_update(struct shash_desc *desc, const u8 *data,
 {
 	struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
 
-	ctx->crc = crc32c(ctx->crc, data, length);
+	ctx->crc = __crc32c_le(ctx->crc, data, length);
 	return 0;
 }
 
@@ -193,7 +105,7 @@ static int chksum_final(struct shash_desc *desc, u8 *out)
 
 static int __chksum_finup(u32 *crcp, const u8 *data, unsigned int len, u8 *out)
 {
-	*(__le32 *)out = ~cpu_to_le32(crc32c(*crcp, data, len));
+	*(__le32 *)out = ~cpu_to_le32(__crc32c_le(*crcp, data, len));
 	return 0;
 }
 
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 41e529a..7281b8a 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -40,9 +40,9 @@ void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
 }
 EXPORT_SYMBOL_GPL(scatterwalk_start);
 
-void *scatterwalk_map(struct scatter_walk *walk, int out)
+void *scatterwalk_map(struct scatter_walk *walk)
 {
-	return crypto_kmap(scatterwalk_page(walk), out) +
+	return kmap_atomic(scatterwalk_page(walk)) +
 	       offset_in_page(walk->offset);
 }
 EXPORT_SYMBOL_GPL(scatterwalk_map);
@@ -83,9 +83,9 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
 		if (len_this_page > nbytes)
 			len_this_page = nbytes;
 
-		vaddr = scatterwalk_map(walk, out);
+		vaddr = scatterwalk_map(walk);
 		memcpy_dir(buf, vaddr, len_this_page, out);
-		scatterwalk_unmap(vaddr, out);
+		scatterwalk_unmap(vaddr);
 
 		scatterwalk_advance(walk, len_this_page);
 
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 9ed9f60..1b991fe 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -21,8 +21,6 @@
 #include <linux/percpu.h>
 #include <asm/byteorder.h>
 
-static DEFINE_PER_CPU(u64[80], msg_schedule);
-
 static inline u64 Ch(u64 x, u64 y, u64 z)
 {
         return z ^ (x & (y ^ z));
@@ -33,11 +31,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z)
         return (x & y) | (z & (x | y));
 }
 
-static inline u64 RORu64(u64 x, u64 y)
-{
-        return (x >> y) | (x << (64 - y));
-}
-
 static const u64 sha512_K[80] = {
         0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
         0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
@@ -68,10 +61,10 @@ static const u64 sha512_K[80] = {
         0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
 };
 
-#define e0(x)       (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
-#define e1(x)       (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
-#define s0(x)       (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
-#define s1(x)       (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+#define e0(x)       (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
+#define e1(x)       (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
+#define s0(x)       (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
+#define s1(x)       (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
 
 static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 {
@@ -80,7 +73,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input)
 
 static inline void BLEND_OP(int I, u64 *W)
 {
-	W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+	W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]);
 }
 
 static void
@@ -89,38 +82,48 @@ sha512_transform(u64 *state, const u8 *input)
 	u64 a, b, c, d, e, f, g, h, t1, t2;
 
 	int i;
-	u64 *W = get_cpu_var(msg_schedule);
+	u64 W[16];
 
 	/* load the input */
         for (i = 0; i < 16; i++)
                 LOAD_OP(i, W, input);
 
-        for (i = 16; i < 80; i++) {
-                BLEND_OP(i, W);
-        }
-
 	/* load the state into our registers */
 	a=state[0];   b=state[1];   c=state[2];   d=state[3];
 	e=state[4];   f=state[5];   g=state[6];   h=state[7];
 
-	/* now iterate */
-	for (i=0; i<80; i+=8) {
-		t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i  ] + W[i  ];
-		t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
-		t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
-		t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
-		t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
-		t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
-		t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
-		t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
-		t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
-		t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
-		t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
-		t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
-		t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
-		t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
-		t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
-		t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+#define SHA512_0_15(i, a, b, c, d, e, f, g, h)			\
+	t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i];	\
+	t2 = e0(a) + Maj(a, b, c);				\
+	d += t1;						\
+	h = t1 + t2
+
+#define SHA512_16_79(i, a, b, c, d, e, f, g, h)			\
+	BLEND_OP(i, W);						\
+	t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16];	\
+	t2 = e0(a) + Maj(a, b, c);				\
+	d += t1;						\
+	h = t1 + t2
+
+	for (i = 0; i < 16; i += 8) {
+		SHA512_0_15(i, a, b, c, d, e, f, g, h);
+		SHA512_0_15(i + 1, h, a, b, c, d, e, f, g);
+		SHA512_0_15(i + 2, g, h, a, b, c, d, e, f);
+		SHA512_0_15(i + 3, f, g, h, a, b, c, d, e);
+		SHA512_0_15(i + 4, e, f, g, h, a, b, c, d);
+		SHA512_0_15(i + 5, d, e, f, g, h, a, b, c);
+		SHA512_0_15(i + 6, c, d, e, f, g, h, a, b);
+		SHA512_0_15(i + 7, b, c, d, e, f, g, h, a);
+	}
+	for (i = 16; i < 80; i += 8) {
+		SHA512_16_79(i, a, b, c, d, e, f, g, h);
+		SHA512_16_79(i + 1, h, a, b, c, d, e, f, g);
+		SHA512_16_79(i + 2, g, h, a, b, c, d, e, f);
+		SHA512_16_79(i + 3, f, g, h, a, b, c, d, e);
+		SHA512_16_79(i + 4, e, f, g, h, a, b, c, d);
+		SHA512_16_79(i + 5, d, e, f, g, h, a, b, c);
+		SHA512_16_79(i + 6, c, d, e, f, g, h, a, b);
+		SHA512_16_79(i + 7, b, c, d, e, f, g, h, a);
 	}
 
 	state[0] += a; state[1] += b; state[2] += c; state[3] += d;
@@ -128,8 +131,6 @@ sha512_transform(u64 *state, const u8 *input)
 
 	/* erase our data */
 	a = b = c = d = e = f = g = h = t1 = t2 = 0;
-	memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
-	put_cpu_var(msg_schedule);
 }
 
 static int
diff --git a/crypto/shash.c b/crypto/shash.c
index 9100912..21fc12e 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -281,10 +281,10 @@ int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
 	if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) {
 		void *data;
 
-		data = crypto_kmap(sg_page(sg), 0);
+		data = kmap_atomic(sg_page(sg));
 		err = crypto_shash_digest(desc, data + offset, nbytes,
 					  req->result);
-		crypto_kunmap(data, 0);
+		kunmap_atomic(data);
 		crypto_yield(desc->flags);
 	} else
 		err = crypto_shash_init(desc) ?:
@@ -420,9 +420,9 @@ static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg,
 
 		desc->flags = hdesc->flags;
 
-		data = crypto_kmap(sg_page(sg), 0);
+		data = kmap_atomic(sg_page(sg));
 		err = crypto_shash_digest(desc, data + offset, nbytes, out);
-		crypto_kunmap(data, 0);
+		kunmap_atomic(data);
 		crypto_yield(desc->flags);
 		goto out;
 	}
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 5afe5d1..d5138e6 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/hsi/Kconfig"
+
 source "drivers/pps/Kconfig"
 
 source "drivers/ptp/Kconfig"
@@ -132,8 +134,14 @@ source "drivers/clocksource/Kconfig"
 
 source "drivers/iommu/Kconfig"
 
+source "drivers/remoteproc/Kconfig"
+
+source "drivers/rpmsg/Kconfig"
+
 source "drivers/virt/Kconfig"
 
 source "drivers/devfreq/Kconfig"
 
+source "drivers/xshm/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index c07be02..71a1f16 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
+obj-y				+= hsi/
 obj-y				+= net/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_FUSION)		+= message/
@@ -120,12 +121,15 @@ obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
 obj-y				+= ieee802154/
+obj-$(CONFIG_XSHM)		+= xshm/
 #common clk code
 obj-y				+= clk/
 
 obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
 obj-$(CONFIG_NFC)		+= nfc/
 obj-$(CONFIG_IOMMU_SUPPORT)	+= iommu/
+obj-$(CONFIG_REMOTEPROC)	+= remoteproc/
+obj-$(CONFIG_RPMSG)		+= rpmsg/
 
 # Virtualization drivers
 obj-$(CONFIG_VIRT_DRIVERS)	+= virt/
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 5b898d4..bb20b03 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -276,7 +276,7 @@ static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab)
 	if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger))
 		return -EINVAL;
 	if (trigger_tab->table_size > PAGE_SIZE ||
-	    trigger_tab->table_size <= trigger_tab->header_size)
+	    trigger_tab->table_size < trigger_tab->header_size)
 		return -EINVAL;
 	if (trigger_tab->entry_count !=
 	    (trigger_tab->table_size - trigger_tab->header_size) /
@@ -340,6 +340,11 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
 			   "The trigger error action table is invalid\n");
 		goto out_rel_header;
 	}
+
+	/* No action structures in the TRIGGER_ERROR table, nothing to do */
+	if (!trigger_tab->entry_count)
+		goto out_rel_header;
+
 	rc = -EIO;
 	table_size = trigger_tab->table_size;
 	r = request_mem_region(trigger_paddr + sizeof(*trigger_tab),
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 9691dd0..d8af325 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -720,13 +720,13 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
 
 		/* FIXME: use a bounce buffer */
 		local_irq_save(flags);
-		buf = kmap_atomic(page, KM_IRQ0);
+		buf = kmap_atomic(page);
 
 		/* do the actual data transfer */
 		ap->ops->sff_data_xfer(qc->dev, buf + offset, qc->sect_size,
 				       do_write);
 
-		kunmap_atomic(buf, KM_IRQ0);
+		kunmap_atomic(buf);
 		local_irq_restore(flags);
 	} else {
 		buf = page_address(page);
@@ -865,13 +865,13 @@ next_sg:
 
 		/* FIXME: use bounce buffer */
 		local_irq_save(flags);
-		buf = kmap_atomic(page, KM_IRQ0);
+		buf = kmap_atomic(page);
 
 		/* do the actual data transfer */
 		consumed = ap->ops->sff_data_xfer(dev,  buf + offset,
 								count, rw);
 
-		kunmap_atomic(buf, KM_IRQ0);
+		kunmap_atomic(buf);
 		local_irq_restore(flags);
 	} else {
 		buf = page_address(page);
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index ec24643..531ceb3 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -242,9 +242,9 @@ static void copy_to_brd(struct brd_device *brd, const void *src,
 	page = brd_lookup_page(brd, sector);
 	BUG_ON(!page);
 
-	dst = kmap_atomic(page, KM_USER1);
+	dst = kmap_atomic(page);
 	memcpy(dst + offset, src, copy);
-	kunmap_atomic(dst, KM_USER1);
+	kunmap_atomic(dst);
 
 	if (copy < n) {
 		src += copy;
@@ -253,9 +253,9 @@ static void copy_to_brd(struct brd_device *brd, const void *src,
 		page = brd_lookup_page(brd, sector);
 		BUG_ON(!page);
 
-		dst = kmap_atomic(page, KM_USER1);
+		dst = kmap_atomic(page);
 		memcpy(dst, src, copy);
-		kunmap_atomic(dst, KM_USER1);
+		kunmap_atomic(dst);
 	}
 }
 
@@ -273,9 +273,9 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
 	copy = min_t(size_t, n, PAGE_SIZE - offset);
 	page = brd_lookup_page(brd, sector);
 	if (page) {
-		src = kmap_atomic(page, KM_USER1);
+		src = kmap_atomic(page);
 		memcpy(dst, src + offset, copy);
-		kunmap_atomic(src, KM_USER1);
+		kunmap_atomic(src);
 	} else
 		memset(dst, 0, copy);
 
@@ -285,9 +285,9 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
 		copy = n - copy;
 		page = brd_lookup_page(brd, sector);
 		if (page) {
-			src = kmap_atomic(page, KM_USER1);
+			src = kmap_atomic(page);
 			memcpy(dst, src, copy);
-			kunmap_atomic(src, KM_USER1);
+			kunmap_atomic(src);
 		} else
 			memset(dst, 0, copy);
 	}
@@ -309,7 +309,7 @@ static int brd_do_bvec(struct brd_device *brd, struct page *page,
 			goto out;
 	}
 
-	mem = kmap_atomic(page, KM_USER0);
+	mem = kmap_atomic(page);
 	if (rw == READ) {
 		copy_from_brd(mem + off, brd, sector, len);
 		flush_dcache_page(page);
@@ -317,7 +317,7 @@ static int brd_do_bvec(struct brd_device *brd, struct page *page,
 		flush_dcache_page(page);
 		copy_to_brd(brd, mem + off, sector, len);
 	}
-	kunmap_atomic(mem, KM_USER0);
+	kunmap_atomic(mem);
 
 out:
 	return err;
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 912f585..3030201 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -289,25 +289,25 @@ static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr)
 	return page_nr;
 }
 
-static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx, const enum km_type km)
+static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx)
 {
 	struct page *page = b->bm_pages[idx];
-	return (unsigned long *) kmap_atomic(page, km);
+	return (unsigned long *) kmap_atomic(page);
 }
 
 static unsigned long *bm_map_pidx(struct drbd_bitmap *b, unsigned int idx)
 {
-	return __bm_map_pidx(b, idx, KM_IRQ1);
+	return __bm_map_pidx(b, idx);
 }
 
-static void __bm_unmap(unsigned long *p_addr, const enum km_type km)
+static void __bm_unmap(unsigned long *p_addr)
 {
-	kunmap_atomic(p_addr, km);
+	kunmap_atomic(p_addr);
 };
 
 static void bm_unmap(unsigned long *p_addr)
 {
-	return __bm_unmap(p_addr, KM_IRQ1);
+	return __bm_unmap(p_addr);
 }
 
 /* long word offset of _bitmap_ sector */
@@ -543,15 +543,15 @@ static unsigned long bm_count_bits(struct drbd_bitmap *b)
 
 	/* all but last page */
 	for (idx = 0; idx < b->bm_number_of_pages - 1; idx++) {
-		p_addr = __bm_map_pidx(b, idx, KM_USER0);
+		p_addr = __bm_map_pidx(b, idx);
 		for (i = 0; i < LWPP; i++)
 			bits += hweight_long(p_addr[i]);
-		__bm_unmap(p_addr, KM_USER0);
+		__bm_unmap(p_addr);
 		cond_resched();
 	}
 	/* last (or only) page */
 	last_word = ((b->bm_bits - 1) & BITS_PER_PAGE_MASK) >> LN2_BPL;
-	p_addr = __bm_map_pidx(b, idx, KM_USER0);
+	p_addr = __bm_map_pidx(b, idx);
 	for (i = 0; i < last_word; i++)
 		bits += hweight_long(p_addr[i]);
 	p_addr[last_word] &= cpu_to_lel(mask);
@@ -559,7 +559,7 @@ static unsigned long bm_count_bits(struct drbd_bitmap *b)
 	/* 32bit arch, may have an unused padding long */
 	if (BITS_PER_LONG == 32 && (last_word & 1) == 0)
 		p_addr[last_word+1] = 0;
-	__bm_unmap(p_addr, KM_USER0);
+	__bm_unmap(p_addr);
 	return bits;
 }
 
@@ -970,11 +970,11 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
 		 * to use pre-allocated page pool */
 		void *src, *dest;
 		page = alloc_page(__GFP_HIGHMEM|__GFP_WAIT);
-		dest = kmap_atomic(page, KM_USER0);
-		src = kmap_atomic(b->bm_pages[page_nr], KM_USER1);
+		dest = kmap_atomic(page);
+		src = kmap_atomic(b->bm_pages[page_nr]);
 		memcpy(dest, src, PAGE_SIZE);
-		kunmap_atomic(src, KM_USER1);
-		kunmap_atomic(dest, KM_USER0);
+		kunmap_atomic(src);
+		kunmap_atomic(dest);
 		bm_store_page_idx(page, page_nr);
 	} else
 		page = b->bm_pages[page_nr];
@@ -1163,7 +1163,7 @@ int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(loc
  * this returns a bit number, NOT a sector!
  */
 static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
-	const int find_zero_bit, const enum km_type km)
+	const int find_zero_bit)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long *p_addr;
@@ -1178,7 +1178,7 @@ static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
 		while (bm_fo < b->bm_bits) {
 			/* bit offset of the first bit in the page */
 			bit_offset = bm_fo & ~BITS_PER_PAGE_MASK;
-			p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo), km);
+			p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo));
 
 			if (find_zero_bit)
 				i = find_next_zero_bit_le(p_addr,
@@ -1187,7 +1187,7 @@ static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
 				i = find_next_bit_le(p_addr,
 						PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK);
 
-			__bm_unmap(p_addr, km);
+			__bm_unmap(p_addr);
 			if (i < PAGE_SIZE*8) {
 				bm_fo = bit_offset + i;
 				if (bm_fo >= b->bm_bits)
@@ -1215,7 +1215,7 @@ static unsigned long bm_find_next(struct drbd_conf *mdev,
 	if (BM_DONT_TEST & b->bm_flags)
 		bm_print_lock_info(mdev);
 
-	i = __bm_find_next(mdev, bm_fo, find_zero_bit, KM_IRQ1);
+	i = __bm_find_next(mdev, bm_fo, find_zero_bit);
 
 	spin_unlock_irq(&b->bm_lock);
 	return i;
@@ -1239,13 +1239,13 @@ unsigned long drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo
 unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo)
 {
 	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
-	return __bm_find_next(mdev, bm_fo, 0, KM_USER1);
+	return __bm_find_next(mdev, bm_fo, 0);
 }
 
 unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo)
 {
 	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
-	return __bm_find_next(mdev, bm_fo, 1, KM_USER1);
+	return __bm_find_next(mdev, bm_fo, 1);
 }
 
 /* returns number of bits actually changed.
@@ -1273,14 +1273,14 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 		unsigned int page_nr = bm_bit_to_page_idx(b, bitnr);
 		if (page_nr != last_page_nr) {
 			if (p_addr)
-				__bm_unmap(p_addr, KM_IRQ1);
+				__bm_unmap(p_addr);
 			if (c < 0)
 				bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
 			else if (c > 0)
 				bm_set_page_need_writeout(b->bm_pages[last_page_nr]);
 			changed_total += c;
 			c = 0;
-			p_addr = __bm_map_pidx(b, page_nr, KM_IRQ1);
+			p_addr = __bm_map_pidx(b, page_nr);
 			last_page_nr = page_nr;
 		}
 		if (val)
@@ -1289,7 +1289,7 @@ static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 			c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr));
 	}
 	if (p_addr)
-		__bm_unmap(p_addr, KM_IRQ1);
+		__bm_unmap(p_addr);
 	if (c < 0)
 		bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
 	else if (c > 0)
@@ -1342,13 +1342,13 @@ static inline void bm_set_full_words_within_one_page(struct drbd_bitmap *b,
 {
 	int i;
 	int bits;
-	unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr], KM_IRQ1);
+	unsigned long *paddr = kmap_atomic(b->bm_pages[page_nr]);
 	for (i = first_word; i < last_word; i++) {
 		bits = hweight_long(paddr[i]);
 		paddr[i] = ~0UL;
 		b->bm_set += BITS_PER_LONG - bits;
 	}
-	kunmap_atomic(paddr, KM_IRQ1);
+	kunmap_atomic(paddr);
 }
 
 /* Same thing as drbd_bm_set_bits,
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index af2a250..e09f9ce 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -2526,10 +2526,10 @@ void drbd_bcast_ee(struct drbd_conf *mdev,
 
 	page = e->pages;
 	page_chain_for_each(page) {
-		void *d = kmap_atomic(page, KM_USER0);
+		void *d = kmap_atomic(page);
 		unsigned l = min_t(unsigned, len, PAGE_SIZE);
 		memcpy(tl, d, l);
-		kunmap_atomic(d, KM_USER0);
+		kunmap_atomic(d);
 		tl = (unsigned short*)((char*)tl + l);
 		len -= l;
 		if (len == 0)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f002577..fde27a9 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -93,16 +93,16 @@ static int transfer_none(struct loop_device *lo, int cmd,
 			 struct page *loop_page, unsigned loop_off,
 			 int size, sector_t real_block)
 {
-	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;
-	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off;
+	char *raw_buf = kmap_atomic(raw_page) + raw_off;
+	char *loop_buf = kmap_atomic(loop_page) + loop_off;
 
 	if (cmd == READ)
 		memcpy(loop_buf, raw_buf, size);
 	else
 		memcpy(raw_buf, loop_buf, size);
 
-	kunmap_atomic(loop_buf, KM_USER1);
-	kunmap_atomic(raw_buf, KM_USER0);
+	kunmap_atomic(loop_buf);
+	kunmap_atomic(raw_buf);
 	cond_resched();
 	return 0;
 }
@@ -112,8 +112,8 @@ static int transfer_xor(struct loop_device *lo, int cmd,
 			struct page *loop_page, unsigned loop_off,
 			int size, sector_t real_block)
 {
-	char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off;
-	char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off;
+	char *raw_buf = kmap_atomic(raw_page) + raw_off;
+	char *loop_buf = kmap_atomic(loop_page) + loop_off;
 	char *in, *out, *key;
 	int i, keysize;
 
@@ -130,8 +130,8 @@ static int transfer_xor(struct loop_device *lo, int cmd,
 	for (i = 0; i < size; i++)
 		*out++ = *in++ ^ key[(i & 511) % keysize];
 
-	kunmap_atomic(loop_buf, KM_USER1);
-	kunmap_atomic(raw_buf, KM_USER0);
+	kunmap_atomic(loop_buf);
+	kunmap_atomic(raw_buf);
 	cond_resched();
 	return 0;
 }
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index d59edea..ba66e44 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -987,14 +987,14 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag
 
 	while (copy_size > 0) {
 		struct bio_vec *src_bvl = bio_iovec_idx(src_bio, seg);
-		void *vfrom = kmap_atomic(src_bvl->bv_page, KM_USER0) +
+		void *vfrom = kmap_atomic(src_bvl->bv_page) +
 			src_bvl->bv_offset + offs;
 		void *vto = page_address(dst_page) + dst_offs;
 		int len = min_t(int, copy_size, src_bvl->bv_len - offs);
 
 		BUG_ON(len < 0);
 		memcpy(vto, vfrom, len);
-		kunmap_atomic(vfrom, KM_USER0);
+		kunmap_atomic(vfrom);
 
 		seg++;
 		offs = 0;
@@ -1019,10 +1019,10 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
 	offs = 0;
 	for (f = 0; f < pkt->frames; f++) {
 		if (bvec[f].bv_page != pkt->pages[p]) {
-			void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset;
+			void *vfrom = kmap_atomic(bvec[f].bv_page) + bvec[f].bv_offset;
 			void *vto = page_address(pkt->pages[p]) + offs;
 			memcpy(vto, vfrom, CD_FRAMESIZE);
-			kunmap_atomic(vfrom, KM_USER0);
+			kunmap_atomic(vfrom);
 			bvec[f].bv_page = pkt->pages[p];
 			bvec[f].bv_offset = offs;
 		} else {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4364303..f166499 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -603,6 +603,7 @@ source "drivers/s390/char/Kconfig"
 config RAMOOPS
 	tristate "Log panic/oops to a RAM buffer"
 	depends on HAS_IOMEM
+	depends on PSTORE
 	default n
 	help
 	  This enables panic and oops messages to be logged to a circular
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 0833896..c9aeb7f 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -263,16 +263,40 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
 
 static int hpet_open(struct inode *inode, struct file *file)
 {
-	struct hpet_dev *devp;
 	struct hpets *hpetp;
-	int i;
 
 	if (file->f_mode & FMODE_WRITE)
 		return -EINVAL;
 
+	hpetp = hpets;
+	/* starting with timer-neutral instance */
+	file->private_data = &hpetp->hp_dev[hpetp->hp_ntimer];
+
+	return 0;
+}
+
+static int hpet_alloc_timer(struct file *file)
+{
+	struct hpet_dev *devp;
+	struct hpets *hpetp;
+	int i;
+
+	/* once acquired, will remain */
+	devp = file->private_data;
+	if (devp->hd_timer)
+		return 0;
+
 	mutex_lock(&hpet_mutex);
 	spin_lock_irq(&hpet_lock);
 
+	/* check for race acquiring */
+	devp = file->private_data;
+	if (devp->hd_timer) {
+		spin_unlock_irq(&hpet_lock);
+		mutex_unlock(&hpet_mutex);
+		return 0;
+	}
+
 	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
 		for (i = 0; i < hpetp->hp_ntimer; i++)
 			if (hpetp->hp_dev[i].hd_flags & HPET_OPEN)
@@ -402,6 +426,11 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 static int hpet_fasync(int fd, struct file *file, int on)
 {
 	struct hpet_dev *devp;
+	int r;
+
+	r = hpet_alloc_timer(file);
+	if (r < 0)
+		return r;
 
 	devp = file->private_data;
 
@@ -420,6 +449,9 @@ static int hpet_release(struct inode *inode, struct file *file)
 	devp = file->private_data;
 	timer = devp->hd_timer;
 
+	if (!timer)
+		goto out;
+
 	spin_lock_irq(&hpet_lock);
 
 	writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK),
@@ -444,7 +476,7 @@ static int hpet_release(struct inode *inode, struct file *file)
 
 	if (irq)
 		free_irq(irq, devp);
-
+out:
 	file->private_data = NULL;
 	return 0;
 }
@@ -593,6 +625,9 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
 		break;
 	case HPET_IE_ON:
 		return hpet_ioctl_ieon(devp);
+	case HPET_ALLOC_TIMER:
+		/* nothing to do */
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -859,7 +894,11 @@ int hpet_alloc(struct hpet_data *hdp)
 		return 0;
 	}
 
-	siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
+	/*
+	 * last hpet_dev will have null timer pointer, gives timer-neutral
+	 * representation of block
+	 */
+	siz = sizeof(struct hpets) + ((hdp->hd_nirqs) *
 				      sizeof(struct hpet_dev));
 
 	hpetp = kzalloc(siz, GFP_KERNEL);
@@ -925,13 +964,16 @@ int hpet_alloc(struct hpet_data *hdp)
 		writeq(mcfg, &hpet->hpet_config);
 	}
 
-	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer; i++, devp++) {
+	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer + 1;
+	     i++, devp++) {
 		struct hpet_timer __iomem *timer;
 
-		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
-
 		devp->hd_hpets = hpetp;
 		devp->hd_hpet = hpet;
+		if (i == hpetp->hp_ntimer)
+			continue;
+
+		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
 		devp->hd_timer = timer;
 
 		/*
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c
index 0bc0cb7..de473ef 100644
--- a/drivers/char/hw_random/tx4939-rng.c
+++ b/drivers/char/hw_random/tx4939-rng.c
@@ -115,10 +115,7 @@ static int __init tx4939_rng_probe(struct platform_device *dev)
 	rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL);
 	if (!rngdev)
 		return -ENOMEM;
-	if (!devm_request_mem_region(&dev->dev, r->start, resource_size(r),
-				     dev_name(&dev->dev)))
-		return -EBUSY;
-	rngdev->base = devm_ioremap(&dev->dev, r->start, resource_size(r));
+	rngdev->base = devm_request_and_ioremap(&dev->dev, r);
 	if (!rngdev->base)
 		return -EBUSY;
 
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c
index 9fec323..5a75d70 100644
--- a/drivers/char/ramoops.c
+++ b/drivers/char/ramoops.c
@@ -2,6 +2,7 @@
  * RAM Oops/Panic logger
  *
  * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * Copyright (C) 2011 Kees Cook <keescook@chromium.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -24,7 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/module.h>
-#include <linux/kmsg_dump.h>
+#include <linux/pstore.h>
 #include <linux/time.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -56,73 +57,156 @@ module_param(dump_oops, int, 0600);
 MODULE_PARM_DESC(dump_oops,
 		"set to 1 to dump oopses, 0 to only dump panics (default 1)");
 
-static struct ramoops_context {
-	struct kmsg_dumper dump;
+struct ramoops_context {
 	void *virt_addr;
 	phys_addr_t phys_addr;
 	unsigned long size;
-	unsigned long record_size;
+	size_t record_size;
 	int dump_oops;
-	int count;
-	int max_count;
-} oops_cxt;
+	unsigned int count;
+	unsigned int max_count;
+	unsigned int read_count;
+	struct pstore_info pstore;
+};
 
 static struct platform_device *dummy;
 static struct ramoops_platform_data *dummy_data;
 
-static void ramoops_do_dump(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
-		const char *s2, unsigned long l2)
+static int ramoops_pstore_open(struct pstore_info *psi)
+{
+	struct ramoops_context *cxt = psi->data;
+
+	cxt->read_count = 0;
+	return 0;
+}
+
+static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
+				   struct timespec *time,
+				   char **buf,
+				   struct pstore_info *psi)
 {
-	struct ramoops_context *cxt = container_of(dumper,
-			struct ramoops_context, dump);
-	unsigned long s1_start, s2_start;
-	unsigned long l1_cpy, l2_cpy;
-	int res, hdr_size;
-	char *buf, *buf_orig;
+	ssize_t size;
+	char *rambuf;
+	struct ramoops_context *cxt = psi->data;
+
+	if (cxt->read_count >= cxt->max_count)
+		return -EINVAL;
+	*id = cxt->read_count++;
+	/* Only supports dmesg output so far. */
+	*type = PSTORE_TYPE_DMESG;
+	/* TODO(kees): Bogus time for the moment. */
+	time->tv_sec = 0;
+	time->tv_nsec = 0;
+
+	rambuf = cxt->virt_addr + (*id * cxt->record_size);
+	size = strnlen(rambuf, cxt->record_size);
+	*buf = kmalloc(size, GFP_KERNEL);
+	if (*buf == NULL)
+		return -ENOMEM;
+	memcpy(*buf, rambuf, size);
+
+	return size;
+}
+
+static int ramoops_pstore_write(enum pstore_type_id type,
+				enum kmsg_dump_reason reason,
+				u64 *id,
+				unsigned int part,
+				size_t size, struct pstore_info *psi)
+{
+	char *buf;
+	size_t res;
 	struct timeval timestamp;
+	struct ramoops_context *cxt = psi->data;
+	size_t available = cxt->record_size;
+
+	/* Currently ramoops is designed to only store dmesg dumps. */
+	if (type != PSTORE_TYPE_DMESG)
+		return -EINVAL;
 
+	/* Out of the various dmesg dump types, ramoops is currently designed
+	 * to only store crash logs, rather than storing general kernel logs.
+	 */
 	if (reason != KMSG_DUMP_OOPS &&
 	    reason != KMSG_DUMP_PANIC)
-		return;
+		return -EINVAL;
 
-	/* Only dump oopses if dump_oops is set */
+	/* Skip Oopes when configured to do so. */
 	if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
-		return;
+		return -EINVAL;
+
+	/* Explicitly only take the first part of any new crash.
+	 * If our buffer is larger than kmsg_bytes, this can never happen,
+	 * and if our buffer is smaller than kmsg_bytes, we don't want the
+	 * report split across multiple records.
+	 */
+	if (part != 1)
+		return -ENOSPC;
 
 	buf = cxt->virt_addr + (cxt->count * cxt->record_size);
-	buf_orig = buf;
 
-	memset(buf, '\0', cxt->record_size);
 	res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
 	buf += res;
+	available -= res;
+
 	do_gettimeofday(&timestamp);
 	res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
 	buf += res;
+	available -= res;
 
-	hdr_size = buf - buf_orig;
-	l2_cpy = min(l2, cxt->record_size - hdr_size);
-	l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
+	if (size > available)
+		size = available;
 
-	s2_start = l2 - l2_cpy;
-	s1_start = l1 - l1_cpy;
-
-	memcpy(buf, s1 + s1_start, l1_cpy);
-	memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
+	memcpy(buf, cxt->pstore.buf, size);
+	memset(buf + size, '\0', available - size);
 
 	cxt->count = (cxt->count + 1) % cxt->max_count;
+
+	return 0;
+}
+
+static int ramoops_pstore_erase(enum pstore_type_id type, u64 id,
+				struct pstore_info *psi)
+{
+	char *buf;
+	struct ramoops_context *cxt = psi->data;
+
+	if (id >= cxt->max_count)
+		return -EINVAL;
+
+	buf = cxt->virt_addr + (id * cxt->record_size);
+	memset(buf, '\0', cxt->record_size);
+
+	return 0;
 }
 
+static struct ramoops_context oops_cxt = {
+	.pstore = {
+		.owner	= THIS_MODULE,
+		.name	= "ramoops",
+		.open	= ramoops_pstore_open,
+		.read	= ramoops_pstore_read,
+		.write	= ramoops_pstore_write,
+		.erase	= ramoops_pstore_erase,
+	},
+};
+
 static int __init ramoops_probe(struct platform_device *pdev)
 {
 	struct ramoops_platform_data *pdata = pdev->dev.platform_data;
 	struct ramoops_context *cxt = &oops_cxt;
 	int err = -EINVAL;
 
+	/* Only a single ramoops area allowed at a time, so fail extra
+	 * probes.
+	 */
+	if (cxt->max_count)
+		goto fail_out;
+
 	if (!pdata->mem_size || !pdata->record_size) {
 		pr_err("The memory size and the record size must be "
 			"non-zero\n");
-		goto fail3;
+		goto fail_out;
 	}
 
 	pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
@@ -131,14 +215,15 @@ static int __init ramoops_probe(struct platform_device *pdev)
 	/* Check for the minimum memory size */
 	if (pdata->mem_size < MIN_MEM_SIZE &&
 			pdata->record_size < MIN_MEM_SIZE) {
-		pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
-		goto fail3;
+		pr_err("memory size too small, minimum is %lu\n",
+			MIN_MEM_SIZE);
+		goto fail_out;
 	}
 
 	if (pdata->mem_size < pdata->record_size) {
 		pr_err("The memory size must be larger than the "
 			"records size\n");
-		goto fail3;
+		goto fail_out;
 	}
 
 	cxt->max_count = pdata->mem_size / pdata->record_size;
@@ -148,23 +233,32 @@ static int __init ramoops_probe(struct platform_device *pdev)
 	cxt->record_size = pdata->record_size;
 	cxt->dump_oops = pdata->dump_oops;
 
+	cxt->pstore.data = cxt;
+	cxt->pstore.bufsize = cxt->record_size;
+	cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
+	spin_lock_init(&cxt->pstore.buf_lock);
+	if (!cxt->pstore.buf) {
+		pr_err("cannot allocate pstore buffer\n");
+		goto fail_clear;
+	}
+
 	if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
-		pr_err("request mem region failed\n");
+		pr_err("request mem region (0x%lx@0x%llx) failed\n",
+			cxt->size, cxt->phys_addr);
 		err = -EINVAL;
-		goto fail3;
+		goto fail_buf;
 	}
 
 	cxt->virt_addr = ioremap(cxt->phys_addr,  cxt->size);
 	if (!cxt->virt_addr) {
 		pr_err("ioremap failed\n");
-		goto fail2;
+		goto fail_mem_region;
 	}
 
-	cxt->dump.dump = ramoops_do_dump;
-	err = kmsg_dump_register(&cxt->dump);
+	err = pstore_register(&cxt->pstore);
 	if (err) {
-		pr_err("registering kmsg dumper failed\n");
-		goto fail1;
+		pr_err("registering with pstore failed\n");
+		goto fail_iounmap;
 	}
 
 	/*
@@ -176,26 +270,43 @@ static int __init ramoops_probe(struct platform_device *pdev)
 	record_size = pdata->record_size;
 	dump_oops = pdata->dump_oops;
 
+	pr_info("attached 0x%lx@0x%llx (%ux0x%zx)\n",
+		cxt->size, cxt->phys_addr, cxt->max_count, cxt->record_size);
+
 	return 0;
 
-fail1:
+fail_iounmap:
 	iounmap(cxt->virt_addr);
-fail2:
+fail_mem_region:
 	release_mem_region(cxt->phys_addr, cxt->size);
-fail3:
+fail_buf:
+	kfree(cxt->pstore.buf);
+fail_clear:
+	cxt->pstore.bufsize = 0;
+	cxt->max_count = 0;
+fail_out:
 	return err;
 }
 
 static int __exit ramoops_remove(struct platform_device *pdev)
 {
+#if 0
+	/* TODO(kees): We cannot unload ramoops since pstore doesn't support
+	 * unregistering yet.
+	 */
 	struct ramoops_context *cxt = &oops_cxt;
 
-	if (kmsg_dump_unregister(&cxt->dump) < 0)
-		pr_warn("could not unregister kmsg_dumper\n");
-
 	iounmap(cxt->virt_addr);
 	release_mem_region(cxt->phys_addr, cxt->size);
+	cxt->max_count = 0;
+
+	/* TODO(kees): When pstore supports unregistering, call it here. */
+	kfree(cxt->pstore.buf);
+	cxt->pstore.bufsize = 0;
+
 	return 0;
+#endif
+	return -EBUSY;
 }
 
 static struct platform_driver ramoops_driver = {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 6d16b4b..e707979 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -293,4 +293,15 @@ config CRYPTO_DEV_S5P
 	  Select this to offload Samsung S5PV210 or S5PC110 from AES
 	  algorithms execution.
 
+config CRYPTO_DEV_TEGRA_AES
+	tristate "Support for TEGRA AES hw engine"
+	depends on ARCH_TEGRA
+	select CRYPTO_AES
+	help
+	  TEGRA processors have AES module accelerator. Select this if you
+	  want to use the TEGRA module for AES algorithms.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called tegra-aes.
+
 endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 53ea501..f3e64ea 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -13,3 +13,4 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
+obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index e73cf2e..534a364 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -1844,6 +1844,25 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha224),cbc(aes))",
+		.driver_name = "authenc-hmac-sha224-cbc-aes-caam",
+		.blocksize = AES_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA224_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+	},
+	{
 		.name = "authenc(hmac(sha256),cbc(aes))",
 		.driver_name = "authenc-hmac-sha256-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
@@ -1864,6 +1883,26 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha384),cbc(aes))",
+		.driver_name = "authenc-hmac-sha384-cbc-aes-caam",
+		.blocksize = AES_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA384_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+	},
+
+	{
 		.name = "authenc(hmac(sha512),cbc(aes))",
 		.driver_name = "authenc-hmac-sha512-cbc-aes-caam",
 		.blocksize = AES_BLOCK_SIZE,
@@ -1922,6 +1961,25 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha224),cbc(des3_ede))",
+		.driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam",
+		.blocksize = DES3_EDE_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = DES3_EDE_BLOCK_SIZE,
+			.maxauthsize = SHA224_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+	},
+	{
 		.name = "authenc(hmac(sha256),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1942,6 +2000,25 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha384),cbc(des3_ede))",
+		.driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam",
+		.blocksize = DES3_EDE_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = DES3_EDE_BLOCK_SIZE,
+			.maxauthsize = SHA384_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+	},
+	{
 		.name = "authenc(hmac(sha512),cbc(des3_ede))",
 		.driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam",
 		.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -2000,6 +2077,25 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha224),cbc(des))",
+		.driver_name = "authenc-hmac-sha224-cbc-des-caam",
+		.blocksize = DES_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = DES_BLOCK_SIZE,
+			.maxauthsize = SHA224_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+	},
+	{
 		.name = "authenc(hmac(sha256),cbc(des))",
 		.driver_name = "authenc-hmac-sha256-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
@@ -2020,6 +2116,25 @@ static struct caam_alg_template driver_algs[] = {
 		.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 	},
 	{
+		.name = "authenc(hmac(sha384),cbc(des))",
+		.driver_name = "authenc-hmac-sha384-cbc-des-caam",
+		.blocksize = DES_BLOCK_SIZE,
+		.template_aead = {
+			.setkey = aead_setkey,
+			.setauthsize = aead_setauthsize,
+			.encrypt = aead_encrypt,
+			.decrypt = aead_decrypt,
+			.givencrypt = aead_givencrypt,
+			.geniv = "<built-in>",
+			.ivsize = DES_BLOCK_SIZE,
+			.maxauthsize = SHA384_DIGEST_SIZE,
+			},
+		.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+		.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+				   OP_ALG_AAI_HMAC_PRECOMP,
+		.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+	},
+	{
 		.name = "authenc(hmac(sha512),cbc(des))",
 		.driver_name = "authenc-hmac-sha512-cbc-des-caam",
 		.blocksize = DES_BLOCK_SIZE,
@@ -2205,7 +2320,8 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
 	alg->cra_blocksize = template->blocksize;
 	alg->cra_alignmask = 0;
 	alg->cra_ctxsize = sizeof(struct caam_ctx);
-	alg->cra_flags = CRYPTO_ALG_ASYNC | template->type;
+	alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+			 template->type;
 	switch (template->type) {
 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
 		alg->cra_type = &crypto_ablkcipher_type;
@@ -2285,12 +2401,12 @@ static int __init caam_algapi_init(void)
 			dev_warn(ctrldev, "%s alg registration failed\n",
 				t_alg->crypto_alg.cra_driver_name);
 			kfree(t_alg);
-		} else {
+		} else
 			list_add_tail(&t_alg->entry, &priv->alg_list);
-			dev_info(ctrldev, "%s\n",
-				 t_alg->crypto_alg.cra_driver_name);
-		}
 	}
+	if (!list_empty(&priv->alg_list))
+		dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
+			 (char *)of_get_property(dev_node, "compatible", NULL));
 
 	return err;
 }
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index 219d09c..f3e36c8 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -393,7 +393,8 @@ static struct crypto_alg geode_cbc_alg = {
 	.cra_driver_name	=	"cbc-aes-geode",
 	.cra_priority		=	400,
 	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-							CRYPTO_ALG_NEED_FALLBACK,
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
+						CRYPTO_ALG_NEED_FALLBACK,
 	.cra_init			=	fallback_init_blk,
 	.cra_exit			=	fallback_exit_blk,
 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
@@ -479,7 +480,8 @@ static struct crypto_alg geode_ecb_alg = {
 	.cra_driver_name	=	"ecb-aes-geode",
 	.cra_priority		=	400,
 	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-							CRYPTO_ALG_NEED_FALLBACK,
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
+						CRYPTO_ALG_NEED_FALLBACK,
 	.cra_init			=	fallback_init_blk,
 	.cra_exit			=	fallback_exit_blk,
 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index fe765f4..c9c4bef 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -1731,9 +1731,9 @@ static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset
 	while (size) {
 		copy = min3(srest, dst->length, size);
 
-		daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
+		daddr = kmap_atomic(sg_page(dst));
 		memcpy(daddr + dst->offset + offset, saddr, copy);
-		kunmap_atomic(daddr, KM_IRQ0);
+		kunmap_atomic(daddr);
 
 		nbytes -= copy;
 		size -= copy;
@@ -1793,17 +1793,17 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error)
 				continue;
 			}
 
-			saddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
+			saddr = kmap_atomic(sg_page(t));
 
 			err = ablkcipher_get(saddr, &t->length, t->offset,
 					dst, nbytes, &nbytes);
 			if (err < 0) {
-				kunmap_atomic(saddr, KM_SOFTIRQ0);
+				kunmap_atomic(saddr);
 				break;
 			}
 
 			idx += err;
-			kunmap_atomic(saddr, KM_SOFTIRQ0);
+			kunmap_atomic(saddr);
 		}
 
 		hifn_cipher_walk_exit(&rctx->walk);
@@ -2494,7 +2494,8 @@ static int hifn_alg_alloc(struct hifn_device *dev, struct hifn_alg_template *t)
 		 t->drv_name, dev->name);
 
 	alg->alg.cra_priority = 300;
-	alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
+	alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC;
 	alg->alg.cra_blocksize = t->bsize;
 	alg->alg.cra_ctxsize = sizeof(struct hifn_context);
 	alg->alg.cra_alignmask = 0;
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 4c20c5b..0053d7e 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -265,7 +265,7 @@ static int setup_crypt_desc(void)
 	BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64);
 	crypt_virt = dma_alloc_coherent(dev,
 			NPE_QLEN * sizeof(struct crypt_ctl),
-			&crypt_phys, GFP_KERNEL);
+			&crypt_phys, GFP_ATOMIC);
 	if (!crypt_virt)
 		return -ENOMEM;
 	memset(crypt_virt, 0, NPE_QLEN * sizeof(struct crypt_ctl));
@@ -1449,6 +1449,7 @@ static int __init ixp_module_init(void)
 			/* block ciphers */
 			cra->cra_type = &crypto_ablkcipher_type;
 			cra->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+					 CRYPTO_ALG_KERN_DRIVER_ONLY |
 					 CRYPTO_ALG_ASYNC;
 			if (!cra->cra_ablkcipher.setkey)
 				cra->cra_ablkcipher.setkey = ablk_setkey;
@@ -1461,6 +1462,7 @@ static int __init ixp_module_init(void)
 			/* authenc */
 			cra->cra_type = &crypto_aead_type;
 			cra->cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					 CRYPTO_ALG_KERN_DRIVER_ONLY |
 					 CRYPTO_ALG_ASYNC;
 			cra->cra_aead.setkey = aead_setkey;
 			cra->cra_aead.setauthsize = aead_setauthsize;
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 597235a..8ad2883 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -898,7 +898,8 @@ struct crypto_alg mv_aes_alg_ecb = {
 	.cra_name		= "ecb(aes)",
 	.cra_driver_name	= "mv-ecb-aes",
 	.cra_priority	= 300,
-	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			  CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC,
 	.cra_blocksize	= 16,
 	.cra_ctxsize	= sizeof(struct mv_ctx),
 	.cra_alignmask	= 0,
@@ -920,7 +921,8 @@ struct crypto_alg mv_aes_alg_cbc = {
 	.cra_name		= "cbc(aes)",
 	.cra_driver_name	= "mv-cbc-aes",
 	.cra_priority	= 300,
-	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_flags	= CRYPTO_ALG_TYPE_ABLKCIPHER |
+			  CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC,
 	.cra_blocksize	= AES_BLOCK_SIZE,
 	.cra_ctxsize	= sizeof(struct mv_ctx),
 	.cra_alignmask	= 0,
@@ -952,7 +954,8 @@ struct ahash_alg mv_sha1_alg = {
 			  .cra_driver_name = "mv-sha1",
 			  .cra_priority = 300,
 			  .cra_flags =
-			  CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+			  CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+			  CRYPTO_ALG_NEED_FALLBACK,
 			  .cra_blocksize = SHA1_BLOCK_SIZE,
 			  .cra_ctxsize = sizeof(struct mv_tfm_hash_ctx),
 			  .cra_init = mv_cra_hash_sha1_init,
@@ -976,7 +979,8 @@ struct ahash_alg mv_hmac_sha1_alg = {
 			  .cra_driver_name = "mv-hmac-sha1",
 			  .cra_priority = 300,
 			  .cra_flags =
-			  CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+			  CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+			  CRYPTO_ALG_NEED_FALLBACK,
 			  .cra_blocksize = SHA1_BLOCK_SIZE,
 			  .cra_ctxsize = sizeof(struct mv_tfm_hash_ctx),
 			  .cra_init = mv_cra_hash_hmac_sha1_init,
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 8944dab..67b97c5 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1402,7 +1402,8 @@ static int __devinit __n2_register_one_cipher(const struct n2_cipher_tmpl *tmpl)
 	snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name);
 	snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s-n2", tmpl->drv_name);
 	alg->cra_priority = N2_CRA_PRIORITY;
-	alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
+	alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+			 CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC;
 	alg->cra_blocksize = tmpl->block_size;
 	p->enc_type = tmpl->enc_type;
 	alg->cra_ctxsize = sizeof(struct n2_cipher_context);
@@ -1493,7 +1494,9 @@ static int __devinit __n2_register_one_ahash(const struct n2_hash_tmpl *tmpl)
 	snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name);
 	snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s-n2", tmpl->name);
 	base->cra_priority = N2_CRA_PRIORITY;
-	base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK;
+	base->cra_flags = CRYPTO_ALG_TYPE_AHASH |
+			  CRYPTO_ALG_KERN_DRIVER_ONLY |
+			  CRYPTO_ALG_NEED_FALLBACK;
 	base->cra_blocksize = tmpl->block_size;
 	base->cra_ctxsize = sizeof(struct n2_hash_ctx);
 	base->cra_module = THIS_MODULE;
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 5b970d9..63e57b5 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -756,7 +756,9 @@ static struct crypto_alg algs[] = {
 	.cra_name		= "ecb(aes)",
 	.cra_driver_name	= "ecb-aes-omap",
 	.cra_priority		= 100,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
 	.cra_alignmask		= 0,
@@ -776,7 +778,9 @@ static struct crypto_alg algs[] = {
 	.cra_name		= "cbc(aes)",
 	.cra_driver_name	= "cbc-aes-omap",
 	.cra_priority		= 100,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
+				  CRYPTO_ALG_KERN_DRIVER_ONLY |
+				  CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct omap_aes_ctx),
 	.cra_alignmask		= 0,
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 6399a8f..a3fd6fc 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -953,6 +953,7 @@ static struct ahash_alg algs[] = {
 		.cra_driver_name	= "omap-sha1",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
 						CRYPTO_ALG_ASYNC |
 						CRYPTO_ALG_NEED_FALLBACK,
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
@@ -975,6 +976,7 @@ static struct ahash_alg algs[] = {
 		.cra_driver_name	= "omap-md5",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
 						CRYPTO_ALG_ASYNC |
 						CRYPTO_ALG_NEED_FALLBACK,
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
@@ -998,6 +1000,7 @@ static struct ahash_alg algs[] = {
 		.cra_driver_name	= "omap-hmac-sha1",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
 						CRYPTO_ALG_ASYNC |
 						CRYPTO_ALG_NEED_FALLBACK,
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
@@ -1022,6 +1025,7 @@ static struct ahash_alg algs[] = {
 		.cra_driver_name	= "omap-hmac-md5",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
+						CRYPTO_ALG_KERN_DRIVER_ONLY |
 						CRYPTO_ALG_ASYNC |
 						CRYPTO_ALG_NEED_FALLBACK,
 		.cra_blocksize		= SHA1_BLOCK_SIZE,
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index 58480d0..410a03c 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -1322,6 +1322,7 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_driver_name = "cbc-aes-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				     CRYPTO_ALG_KERN_DRIVER_ONLY |
 				     CRYPTO_ALG_ASYNC |
 				     CRYPTO_ALG_NEED_FALLBACK,
 			.cra_blocksize = AES_BLOCK_SIZE,
@@ -1349,6 +1350,7 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_driver_name = "ecb-aes-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				CRYPTO_ALG_KERN_DRIVER_ONLY |
 				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
@@ -1373,7 +1375,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "cbc(des)",
 			.cra_driver_name = "cbc-des-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
 			.cra_type = &crypto_ablkcipher_type,
@@ -1398,7 +1402,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "ecb(des)",
 			.cra_driver_name = "ecb-des-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
 			.cra_type = &crypto_ablkcipher_type,
@@ -1422,7 +1428,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "cbc(des3_ede)",
 			.cra_driver_name = "cbc-des3-ede-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
 			.cra_type = &crypto_ablkcipher_type,
@@ -1447,7 +1455,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "ecb(des3_ede)",
 			.cra_driver_name = "ecb-des3-ede-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
 			.cra_type = &crypto_ablkcipher_type,
@@ -1472,7 +1482,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
 			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1500,7 +1512,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(sha256),cbc(aes))",
 			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1527,7 +1541,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(md5),cbc(aes))",
 			.cra_driver_name = "authenc-hmac-md5-cbc-aes-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1554,7 +1570,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
 			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1582,7 +1600,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
 			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1609,7 +1629,9 @@ static struct spacc_alg ipsec_engine_algs[] = {
 			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
 			.cra_driver_name = "authenc-hmac-md5-cbc-3des-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
 			.cra_type = &crypto_aead_type,
@@ -1639,7 +1661,9 @@ static struct spacc_alg l2_engine_algs[] = {
 			.cra_name = "f8(kasumi)",
 			.cra_driver_name = "f8-kasumi-picoxcell",
 			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
-			.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER |
+					CRYPTO_ALG_ASYNC |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
 			.cra_blocksize = 8,
 			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
 			.cra_type = &crypto_ablkcipher_type,
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 3376bca..bc986f8 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -518,7 +518,8 @@ static struct crypto_alg algs[] = {
 		.cra_driver_name	= "ecb-aes-s5p",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
-					  CRYPTO_ALG_ASYNC,
+					  CRYPTO_ALG_ASYNC |
+					  CRYPTO_ALG_KERN_DRIVER_ONLY,
 		.cra_blocksize		= AES_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct s5p_aes_ctx),
 		.cra_alignmask		= 0x0f,
@@ -538,7 +539,8 @@ static struct crypto_alg algs[] = {
 		.cra_driver_name	= "cbc-aes-s5p",
 		.cra_priority		= 100,
 		.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER |
-					  CRYPTO_ALG_ASYNC,
+					  CRYPTO_ALG_ASYNC |
+					  CRYPTO_ALG_KERN_DRIVER_ONLY,
 		.cra_blocksize		= AES_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct s5p_aes_ctx),
 		.cra_alignmask		= 0x0f,
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 2d8c789..dc641c7 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -2648,6 +2648,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
 	alg->cra_priority = TALITOS_CRA_PRIORITY;
 	alg->cra_alignmask = 0;
 	alg->cra_ctxsize = sizeof(struct talitos_ctx);
+	alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY;
 
 	t_alg->dev = dev;
 
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
new file mode 100644
index 0000000..422a976
--- /dev/null
+++ b/drivers/crypto/tegra-aes.c
@@ -0,0 +1,1096 @@
+/*
+ * drivers/crypto/tegra-aes.c
+ *
+ * Driver for NVIDIA Tegra AES hardware engine residing inside the
+ * Bit Stream Engine for Video (BSEV) hardware block.
+ *
+ * The programming sequence for this engine is with the help
+ * of commands which travel via a command queue residing between the
+ * CPU and the BSEV block. The BSEV engine has an internal RAM (VRAM)
+ * where the final input plaintext, keys and the IV have to be copied
+ * before starting the encrypt/decrypt operation.
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+
+#include <mach/clk.h>
+
+#include <crypto/scatterwalk.h>
+#include <crypto/aes.h>
+#include <crypto/internal/rng.h>
+
+#include "tegra-aes.h"
+
+#define FLAGS_MODE_MASK			0x00FF
+#define FLAGS_ENCRYPT			BIT(0)
+#define FLAGS_CBC			BIT(1)
+#define FLAGS_GIV			BIT(2)
+#define FLAGS_RNG			BIT(3)
+#define FLAGS_OFB			BIT(4)
+#define FLAGS_NEW_KEY			BIT(5)
+#define FLAGS_NEW_IV			BIT(6)
+#define FLAGS_INIT			BIT(7)
+#define FLAGS_FAST			BIT(8)
+#define FLAGS_BUSY			9
+
+/*
+ * Defines AES engine Max process bytes size in one go, which takes 1 msec.
+ * AES engine spends about 176 cycles/16-bytes or 11 cycles/byte
+ * The duration CPU can use the BSE to 1 msec, then the number of available
+ * cycles of AVP/BSE is 216K. In this duration, AES can process 216/11 ~= 19KB
+ * Based on this AES_HW_DMA_BUFFER_SIZE_BYTES is configured to 16KB.
+ */
+#define AES_HW_DMA_BUFFER_SIZE_BYTES 0x4000
+
+/*
+ * The key table length is 64 bytes
+ * (This includes first upto 32 bytes key + 16 bytes original initial vector
+ * and 16 bytes updated initial vector)
+ */
+#define AES_HW_KEY_TABLE_LENGTH_BYTES 64
+
+/*
+ * The memory being used is divides as follows:
+ * 1. Key - 32 bytes
+ * 2. Original IV - 16 bytes
+ * 3. Updated IV - 16 bytes
+ * 4. Key schedule - 256 bytes
+ *
+ * 1+2+3 constitute the hw key table.
+ */
+#define AES_HW_IV_SIZE 16
+#define AES_HW_KEYSCHEDULE_LEN 256
+#define AES_IVKEY_SIZE (AES_HW_KEY_TABLE_LENGTH_BYTES + AES_HW_KEYSCHEDULE_LEN)
+
+/* Define commands required for AES operation */
+enum {
+	CMD_BLKSTARTENGINE = 0x0E,
+	CMD_DMASETUP = 0x10,
+	CMD_DMACOMPLETE = 0x11,
+	CMD_SETTABLE = 0x15,
+	CMD_MEMDMAVD = 0x22,
+};
+
+/* Define sub-commands */
+enum {
+	SUBCMD_VRAM_SEL = 0x1,
+	SUBCMD_CRYPTO_TABLE_SEL = 0x3,
+	SUBCMD_KEY_TABLE_SEL = 0x8,
+};
+
+/* memdma_vd command */
+#define MEMDMA_DIR_DTOVRAM		0 /* sdram -> vram */
+#define MEMDMA_DIR_VTODRAM		1 /* vram -> sdram */
+#define MEMDMA_DIR_SHIFT		25
+#define MEMDMA_NUM_WORDS_SHIFT		12
+
+/* command queue bit shifts */
+enum {
+	CMDQ_KEYTABLEADDR_SHIFT = 0,
+	CMDQ_KEYTABLEID_SHIFT = 17,
+	CMDQ_VRAMSEL_SHIFT = 23,
+	CMDQ_TABLESEL_SHIFT = 24,
+	CMDQ_OPCODE_SHIFT = 26,
+};
+
+/*
+ * The secure key slot contains a unique secure key generated
+ * and loaded by the bootloader. This slot is marked as non-accessible
+ * to the kernel.
+ */
+#define SSK_SLOT_NUM		4
+
+#define AES_NR_KEYSLOTS		8
+#define TEGRA_AES_QUEUE_LENGTH	50
+#define DEFAULT_RNG_BLK_SZ	16
+
+/* The command queue depth */
+#define AES_HW_MAX_ICQ_LENGTH	5
+
+struct tegra_aes_slot {
+	struct list_head node;
+	int slot_num;
+};
+
+static struct tegra_aes_slot ssk = {
+	.slot_num = SSK_SLOT_NUM,
+};
+
+struct tegra_aes_reqctx {
+	unsigned long mode;
+};
+
+struct tegra_aes_dev {
+	struct device *dev;
+	void __iomem *io_base;
+	dma_addr_t ivkey_phys_base;
+	void __iomem *ivkey_base;
+	struct clk *aes_clk;
+	struct tegra_aes_ctx *ctx;
+	int irq;
+	unsigned long flags;
+	struct completion op_complete;
+	u32 *buf_in;
+	dma_addr_t dma_buf_in;
+	u32 *buf_out;
+	dma_addr_t dma_buf_out;
+	u8 *iv;
+	u8 dt[DEFAULT_RNG_BLK_SZ];
+	int ivlen;
+	u64 ctr;
+	spinlock_t lock;
+	struct crypto_queue queue;
+	struct tegra_aes_slot *slots;
+	struct ablkcipher_request *req;
+	size_t total;
+	struct scatterlist *in_sg;
+	size_t in_offset;
+	struct scatterlist *out_sg;
+	size_t out_offset;
+};
+
+static struct tegra_aes_dev *aes_dev;
+
+struct tegra_aes_ctx {
+	struct tegra_aes_dev *dd;
+	unsigned long flags;
+	struct tegra_aes_slot *slot;
+	u8 key[AES_MAX_KEY_SIZE];
+	size_t keylen;
+};
+
+static struct tegra_aes_ctx rng_ctx = {
+	.flags = FLAGS_NEW_KEY,
+	.keylen = AES_KEYSIZE_128,
+};
+
+/* keep registered devices data here */
+static struct list_head dev_list;
+static DEFINE_SPINLOCK(list_lock);
+static DEFINE_MUTEX(aes_lock);
+
+static void aes_workqueue_handler(struct work_struct *work);
+static DECLARE_WORK(aes_work, aes_workqueue_handler);
+static struct workqueue_struct *aes_wq;
+
+extern unsigned long long tegra_chip_uid(void);
+
+static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset)
+{
+	return readl(dd->io_base + offset);
+}
+
+static inline void aes_writel(struct tegra_aes_dev *dd, u32 val, u32 offset)
+{
+	writel(val, dd->io_base + offset);
+}
+
+static int aes_start_crypt(struct tegra_aes_dev *dd, u32 in_addr, u32 out_addr,
+	int nblocks, int mode, bool upd_iv)
+{
+	u32 cmdq[AES_HW_MAX_ICQ_LENGTH];
+	int i, eng_busy, icq_empty, ret;
+	u32 value;
+
+	/* reset all the interrupt bits */
+	aes_writel(dd, 0xFFFFFFFF, TEGRA_AES_INTR_STATUS);
+
+	/* enable error, dma xfer complete interrupts */
+	aes_writel(dd, 0x33, TEGRA_AES_INT_ENB);
+
+	cmdq[0] = CMD_DMASETUP << CMDQ_OPCODE_SHIFT;
+	cmdq[1] = in_addr;
+	cmdq[2] = CMD_BLKSTARTENGINE << CMDQ_OPCODE_SHIFT | (nblocks-1);
+	cmdq[3] = CMD_DMACOMPLETE << CMDQ_OPCODE_SHIFT;
+
+	value = aes_readl(dd, TEGRA_AES_CMDQUE_CONTROL);
+	/* access SDRAM through AHB */
+	value &= ~TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD;
+	value &= ~TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD;
+	value |= TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD |
+		 TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD |
+		 TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD;
+	aes_writel(dd, value, TEGRA_AES_CMDQUE_CONTROL);
+	dev_dbg(dd->dev, "cmd_q_ctrl=0x%x", value);
+
+	value = (0x1 << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT) |
+		((dd->ctx->keylen * 8) <<
+			TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT) |
+		((u32)upd_iv << TEGRA_AES_SECURE_IV_SELECT_SHIFT);
+
+	if (mode & FLAGS_CBC) {
+		value |= ((((mode & FLAGS_ENCRYPT) ? 2 : 3)
+				<< TEGRA_AES_SECURE_XOR_POS_SHIFT) |
+			(((mode & FLAGS_ENCRYPT) ? 2 : 3)
+				<< TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT) |
+			((mode & FLAGS_ENCRYPT) ? 1 : 0)
+				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT);
+	} else if (mode & FLAGS_OFB) {
+		value |= ((TEGRA_AES_SECURE_XOR_POS_FIELD) |
+			(2 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT) |
+			(TEGRA_AES_SECURE_CORE_SEL_FIELD));
+	} else if (mode & FLAGS_RNG) {
+		value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0)
+				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT |
+			  TEGRA_AES_SECURE_RNG_ENB_FIELD);
+	} else {
+		value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0)
+				<< TEGRA_AES_SECURE_CORE_SEL_SHIFT);
+	}
+
+	dev_dbg(dd->dev, "secure_in_sel=0x%x", value);
+	aes_writel(dd, value, TEGRA_AES_SECURE_INPUT_SELECT);
+
+	aes_writel(dd, out_addr, TEGRA_AES_SECURE_DEST_ADDR);
+	INIT_COMPLETION(dd->op_complete);
+
+	for (i = 0; i < AES_HW_MAX_ICQ_LENGTH - 1; i++) {
+		do {
+			value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
+			eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
+			icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
+		} while (eng_busy & (!icq_empty));
+		aes_writel(dd, cmdq[i], TEGRA_AES_ICMDQUE_WR);
+	}
+
+	ret = wait_for_completion_timeout(&dd->op_complete,
+					  msecs_to_jiffies(150));
+	if (ret == 0) {
+		dev_err(dd->dev, "timed out (0x%x)\n",
+			aes_readl(dd, TEGRA_AES_INTR_STATUS));
+		return -ETIMEDOUT;
+	}
+
+	aes_writel(dd, cmdq[AES_HW_MAX_ICQ_LENGTH - 1], TEGRA_AES_ICMDQUE_WR);
+	return 0;
+}
+
+static void aes_release_key_slot(struct tegra_aes_slot *slot)
+{
+	if (slot->slot_num == SSK_SLOT_NUM)
+		return;
+
+	spin_lock(&list_lock);
+	list_add_tail(&slot->node, &dev_list);
+	slot = NULL;
+	spin_unlock(&list_lock);
+}
+
+static struct tegra_aes_slot *aes_find_key_slot(void)
+{
+	struct tegra_aes_slot *slot = NULL;
+	struct list_head *new_head;
+	int empty;
+
+	spin_lock(&list_lock);
+	empty = list_empty(&dev_list);
+	if (!empty) {
+		slot = list_entry(&dev_list, struct tegra_aes_slot, node);
+		new_head = dev_list.next;
+		list_del(&dev_list);
+		dev_list.next = new_head->next;
+		dev_list.prev = NULL;
+	}
+	spin_unlock(&list_lock);
+
+	return slot;
+}
+
+static int aes_set_key(struct tegra_aes_dev *dd)
+{
+	u32 value, cmdq[2];
+	struct tegra_aes_ctx *ctx = dd->ctx;
+	int eng_busy, icq_empty, dma_busy;
+	bool use_ssk = false;
+
+	/* use ssk? */
+	if (!dd->ctx->slot) {
+		dev_dbg(dd->dev, "using ssk");
+		dd->ctx->slot = &ssk;
+		use_ssk = true;
+	}
+
+	/* enable key schedule generation in hardware */
+	value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG_EXT);
+	value &= ~TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD;
+	aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG_EXT);
+
+	/* select the key slot */
+	value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG);
+	value &= ~TEGRA_AES_SECURE_KEY_INDEX_FIELD;
+	value |= (ctx->slot->slot_num << TEGRA_AES_SECURE_KEY_INDEX_SHIFT);
+	aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG);
+
+	if (use_ssk)
+		return 0;
+
+	/* copy the key table from sdram to vram */
+	cmdq[0] = CMD_MEMDMAVD << CMDQ_OPCODE_SHIFT |
+		MEMDMA_DIR_DTOVRAM << MEMDMA_DIR_SHIFT |
+		AES_HW_KEY_TABLE_LENGTH_BYTES / sizeof(u32) <<
+			MEMDMA_NUM_WORDS_SHIFT;
+	cmdq[1] = (u32)dd->ivkey_phys_base;
+
+	aes_writel(dd, cmdq[0], TEGRA_AES_ICMDQUE_WR);
+	aes_writel(dd, cmdq[1], TEGRA_AES_ICMDQUE_WR);
+
+	do {
+		value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
+		eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
+		icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
+		dma_busy = value & TEGRA_AES_DMA_BUSY_FIELD;
+	} while (eng_busy & (!icq_empty) & dma_busy);
+
+	/* settable command to get key into internal registers */
+	value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT |
+		SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT |
+		SUBCMD_VRAM_SEL << CMDQ_VRAMSEL_SHIFT |
+		(SUBCMD_KEY_TABLE_SEL | ctx->slot->slot_num) <<
+			CMDQ_KEYTABLEID_SHIFT;
+	aes_writel(dd, value, TEGRA_AES_ICMDQUE_WR);
+
+	do {
+		value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
+		eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD;
+		icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD;
+	} while (eng_busy & (!icq_empty));
+
+	return 0;
+}
+
+static int tegra_aes_handle_req(struct tegra_aes_dev *dd)
+{
+	struct crypto_async_request *async_req, *backlog;
+	struct crypto_ablkcipher *tfm;
+	struct tegra_aes_ctx *ctx;
+	struct tegra_aes_reqctx *rctx;
+	struct ablkcipher_request *req;
+	unsigned long flags;
+	int dma_max = AES_HW_DMA_BUFFER_SIZE_BYTES;
+	int ret = 0, nblocks, total;
+	int count = 0;
+	dma_addr_t addr_in, addr_out;
+	struct scatterlist *in_sg, *out_sg;
+
+	if (!dd)
+		return -EINVAL;
+
+	spin_lock_irqsave(&dd->lock, flags);
+	backlog = crypto_get_backlog(&dd->queue);
+	async_req = crypto_dequeue_request(&dd->queue);
+	if (!async_req)
+		clear_bit(FLAGS_BUSY, &dd->flags);
+	spin_unlock_irqrestore(&dd->lock, flags);
+
+	if (!async_req)
+		return -ENODATA;
+
+	if (backlog)
+		backlog->complete(backlog, -EINPROGRESS);
+
+	req = ablkcipher_request_cast(async_req);
+
+	dev_dbg(dd->dev, "%s: get new req\n", __func__);
+
+	if (!req->src || !req->dst)
+		return -EINVAL;
+
+	/* take mutex to access the aes hw */
+	mutex_lock(&aes_lock);
+
+	/* assign new request to device */
+	dd->req = req;
+	dd->total = req->nbytes;
+	dd->in_offset = 0;
+	dd->in_sg = req->src;
+	dd->out_offset = 0;
+	dd->out_sg = req->dst;
+
+	in_sg = dd->in_sg;
+	out_sg = dd->out_sg;
+
+	total = dd->total;
+
+	tfm = crypto_ablkcipher_reqtfm(req);
+	rctx = ablkcipher_request_ctx(req);
+	ctx = crypto_ablkcipher_ctx(tfm);
+	rctx->mode &= FLAGS_MODE_MASK;
+	dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode;
+
+	dd->iv = (u8 *)req->info;
+	dd->ivlen = crypto_ablkcipher_ivsize(tfm);
+
+	/* assign new context to device */
+	ctx->dd = dd;
+	dd->ctx = ctx;
+
+	if (ctx->flags & FLAGS_NEW_KEY) {
+		/* copy the key */
+		memcpy(dd->ivkey_base, ctx->key, ctx->keylen);
+		memset(dd->ivkey_base + ctx->keylen, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - ctx->keylen);
+		aes_set_key(dd);
+		ctx->flags &= ~FLAGS_NEW_KEY;
+	}
+
+	if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && dd->iv) {
+		/* set iv to the aes hw slot
+		 * Hw generates updated iv only after iv is set in slot.
+		 * So key and iv is passed asynchronously.
+		 */
+		memcpy(dd->buf_in, dd->iv, dd->ivlen);
+
+		ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
+				      dd->dma_buf_out, 1, FLAGS_CBC, false);
+		if (ret < 0) {
+			dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
+			goto out;
+		}
+	}
+
+	while (total) {
+		dev_dbg(dd->dev, "remain: %d\n", total);
+		ret = dma_map_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE);
+		if (!ret) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			goto out;
+		}
+
+		ret = dma_map_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE);
+		if (!ret) {
+			dev_err(dd->dev, "dma_map_sg() error\n");
+			dma_unmap_sg(dd->dev, dd->in_sg,
+				1, DMA_TO_DEVICE);
+			goto out;
+		}
+
+		addr_in = sg_dma_address(in_sg);
+		addr_out = sg_dma_address(out_sg);
+		dd->flags |= FLAGS_FAST;
+		count = min_t(int, sg_dma_len(in_sg), dma_max);
+		WARN_ON(sg_dma_len(in_sg) != sg_dma_len(out_sg));
+		nblocks = DIV_ROUND_UP(count, AES_BLOCK_SIZE);
+
+		ret = aes_start_crypt(dd, addr_in, addr_out, nblocks,
+			dd->flags, true);
+
+		dma_unmap_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE);
+		dma_unmap_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE);
+
+		if (ret < 0) {
+			dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
+			goto out;
+		}
+		dd->flags &= ~FLAGS_FAST;
+
+		dev_dbg(dd->dev, "out: copied %d\n", count);
+		total -= count;
+		in_sg = sg_next(in_sg);
+		out_sg = sg_next(out_sg);
+		WARN_ON(((total != 0) && (!in_sg || !out_sg)));
+	}
+
+out:
+	mutex_unlock(&aes_lock);
+
+	dd->total = total;
+
+	if (dd->req->base.complete)
+		dd->req->base.complete(&dd->req->base, ret);
+
+	dev_dbg(dd->dev, "%s: exit\n", __func__);
+	return ret;
+}
+
+static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+			    unsigned int keylen)
+{
+	struct tegra_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	struct tegra_aes_dev *dd = aes_dev;
+	struct tegra_aes_slot *key_slot;
+
+	if ((keylen != AES_KEYSIZE_128) && (keylen != AES_KEYSIZE_192) &&
+		(keylen != AES_KEYSIZE_256)) {
+		dev_err(dd->dev, "unsupported key size\n");
+		crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	dev_dbg(dd->dev, "keylen: %d\n", keylen);
+
+	ctx->dd = dd;
+
+	if (key) {
+		if (!ctx->slot) {
+			key_slot = aes_find_key_slot();
+			if (!key_slot) {
+				dev_err(dd->dev, "no empty slot\n");
+				return -ENOMEM;
+			}
+
+			ctx->slot = key_slot;
+		}
+
+		memcpy(ctx->key, key, keylen);
+		ctx->keylen = keylen;
+	}
+
+	ctx->flags |= FLAGS_NEW_KEY;
+	dev_dbg(dd->dev, "done\n");
+	return 0;
+}
+
+static void aes_workqueue_handler(struct work_struct *work)
+{
+	struct tegra_aes_dev *dd = aes_dev;
+	int ret;
+
+	ret = clk_enable(dd->aes_clk);
+	if (ret)
+		BUG_ON("clock enable failed");
+
+	/* empty the crypto queue and then return */
+	do {
+		ret = tegra_aes_handle_req(dd);
+	} while (!ret);
+
+	clk_disable(dd->aes_clk);
+}
+
+static irqreturn_t aes_irq(int irq, void *dev_id)
+{
+	struct tegra_aes_dev *dd = (struct tegra_aes_dev *)dev_id;
+	u32 value = aes_readl(dd, TEGRA_AES_INTR_STATUS);
+	int busy = test_bit(FLAGS_BUSY, &dd->flags);
+
+	if (!busy) {
+		dev_dbg(dd->dev, "spurious interrupt\n");
+		return IRQ_NONE;
+	}
+
+	dev_dbg(dd->dev, "irq_stat: 0x%x\n", value);
+	if (value & TEGRA_AES_INT_ERROR_MASK)
+		aes_writel(dd, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS);
+
+	if (!(value & TEGRA_AES_ENGINE_BUSY_FIELD))
+		complete(&dd->op_complete);
+	else
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
+static int tegra_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
+{
+	struct tegra_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct tegra_aes_dev *dd = aes_dev;
+	unsigned long flags;
+	int err = 0;
+	int busy;
+
+	dev_dbg(dd->dev, "nbytes: %d, enc: %d, cbc: %d, ofb: %d\n",
+		req->nbytes, !!(mode & FLAGS_ENCRYPT),
+		!!(mode & FLAGS_CBC), !!(mode & FLAGS_OFB));
+
+	rctx->mode = mode;
+
+	spin_lock_irqsave(&dd->lock, flags);
+	err = ablkcipher_enqueue_request(&dd->queue, req);
+	busy = test_and_set_bit(FLAGS_BUSY, &dd->flags);
+	spin_unlock_irqrestore(&dd->lock, flags);
+
+	if (!busy)
+		queue_work(aes_wq, &aes_work);
+
+	return err;
+}
+
+static int tegra_aes_ecb_encrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, FLAGS_ENCRYPT);
+}
+
+static int tegra_aes_ecb_decrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, 0);
+}
+
+static int tegra_aes_cbc_encrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC);
+}
+
+static int tegra_aes_cbc_decrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, FLAGS_CBC);
+}
+
+static int tegra_aes_ofb_encrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_OFB);
+}
+
+static int tegra_aes_ofb_decrypt(struct ablkcipher_request *req)
+{
+	return tegra_aes_crypt(req, FLAGS_OFB);
+}
+
+static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
+				unsigned int dlen)
+{
+	struct tegra_aes_dev *dd = aes_dev;
+	struct tegra_aes_ctx *ctx = &rng_ctx;
+	int ret, i;
+	u8 *dest = rdata, *dt = dd->dt;
+
+	/* take mutex to access the aes hw */
+	mutex_lock(&aes_lock);
+
+	ret = clk_enable(dd->aes_clk);
+	if (ret)
+		return ret;
+
+	ctx->dd = dd;
+	dd->ctx = ctx;
+	dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
+
+	memcpy(dd->buf_in, dt, DEFAULT_RNG_BLK_SZ);
+
+	ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
+			      (u32)dd->dma_buf_out, 1, dd->flags, true);
+	if (ret < 0) {
+		dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
+		dlen = ret;
+		goto out;
+	}
+	memcpy(dest, dd->buf_out, dlen);
+
+	/* update the DT */
+	for (i = DEFAULT_RNG_BLK_SZ - 1; i >= 0; i--) {
+		dt[i] += 1;
+		if (dt[i] != 0)
+			break;
+	}
+
+out:
+	clk_disable(dd->aes_clk);
+	mutex_unlock(&aes_lock);
+
+	dev_dbg(dd->dev, "%s: done\n", __func__);
+	return dlen;
+}
+
+static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
+			       unsigned int slen)
+{
+	struct tegra_aes_dev *dd = aes_dev;
+	struct tegra_aes_ctx *ctx = &rng_ctx;
+	struct tegra_aes_slot *key_slot;
+	struct timespec ts;
+	int ret = 0;
+	u64 nsec, tmp[2];
+	u8 *dt;
+
+	if (!ctx || !dd) {
+		dev_err(dd->dev, "ctx=0x%x, dd=0x%x\n",
+			(unsigned int)ctx, (unsigned int)dd);
+		return -EINVAL;
+	}
+
+	if (slen < (DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
+		dev_err(dd->dev, "seed size invalid");
+		return -ENOMEM;
+	}
+
+	/* take mutex to access the aes hw */
+	mutex_lock(&aes_lock);
+
+	if (!ctx->slot) {
+		key_slot = aes_find_key_slot();
+		if (!key_slot) {
+			dev_err(dd->dev, "no empty slot\n");
+			mutex_unlock(&aes_lock);
+			return -ENOMEM;
+		}
+		ctx->slot = key_slot;
+	}
+
+	ctx->dd = dd;
+	dd->ctx = ctx;
+	dd->ctr = 0;
+
+	ctx->keylen = AES_KEYSIZE_128;
+	ctx->flags |= FLAGS_NEW_KEY;
+
+	/* copy the key to the key slot */
+	memcpy(dd->ivkey_base, seed + DEFAULT_RNG_BLK_SZ, AES_KEYSIZE_128);
+	memset(dd->ivkey_base + AES_KEYSIZE_128, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - AES_KEYSIZE_128);
+
+	dd->iv = seed;
+	dd->ivlen = slen;
+
+	dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
+
+	ret = clk_enable(dd->aes_clk);
+	if (ret)
+		return ret;
+
+	aes_set_key(dd);
+
+	/* set seed to the aes hw slot */
+	memcpy(dd->buf_in, dd->iv, DEFAULT_RNG_BLK_SZ);
+	ret = aes_start_crypt(dd, (u32)dd->dma_buf_in,
+			      dd->dma_buf_out, 1, FLAGS_CBC, false);
+	if (ret < 0) {
+		dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret);
+		goto out;
+	}
+
+	if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) {
+		dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128;
+	} else {
+		getnstimeofday(&ts);
+		nsec = timespec_to_ns(&ts);
+		do_div(nsec, 1000);
+		nsec ^= dd->ctr << 56;
+		dd->ctr++;
+		tmp[0] = nsec;
+		tmp[1] = tegra_chip_uid();
+		dt = (u8 *)tmp;
+	}
+	memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
+
+out:
+	clk_disable(dd->aes_clk);
+	mutex_unlock(&aes_lock);
+
+	dev_dbg(dd->dev, "%s: done\n", __func__);
+	return ret;
+}
+
+static int tegra_aes_cra_init(struct crypto_tfm *tfm)
+{
+	tfm->crt_ablkcipher.reqsize = sizeof(struct tegra_aes_reqctx);
+
+	return 0;
+}
+
+void tegra_aes_cra_exit(struct crypto_tfm *tfm)
+{
+	struct tegra_aes_ctx *ctx =
+		crypto_ablkcipher_ctx((struct crypto_ablkcipher *)tfm);
+
+	if (ctx && ctx->slot)
+		aes_release_key_slot(ctx->slot);
+}
+
+static struct crypto_alg algs[] = {
+	{
+		.cra_name = "ecb(aes)",
+		.cra_driver_name = "ecb-aes-tegra",
+		.cra_priority = 300,
+		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+		.cra_blocksize = AES_BLOCK_SIZE,
+		.cra_alignmask = 3,
+		.cra_type = &crypto_ablkcipher_type,
+		.cra_u.ablkcipher = {
+			.min_keysize = AES_MIN_KEY_SIZE,
+			.max_keysize = AES_MAX_KEY_SIZE,
+			.setkey = tegra_aes_setkey,
+			.encrypt = tegra_aes_ecb_encrypt,
+			.decrypt = tegra_aes_ecb_decrypt,
+		},
+	}, {
+		.cra_name = "cbc(aes)",
+		.cra_driver_name = "cbc-aes-tegra",
+		.cra_priority = 300,
+		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+		.cra_blocksize = AES_BLOCK_SIZE,
+		.cra_alignmask = 3,
+		.cra_type = &crypto_ablkcipher_type,
+		.cra_u.ablkcipher = {
+			.min_keysize = AES_MIN_KEY_SIZE,
+			.max_keysize = AES_MAX_KEY_SIZE,
+			.ivsize = AES_MIN_KEY_SIZE,
+			.setkey = tegra_aes_setkey,
+			.encrypt = tegra_aes_cbc_encrypt,
+			.decrypt = tegra_aes_cbc_decrypt,
+		}
+	}, {
+		.cra_name = "ofb(aes)",
+		.cra_driver_name = "ofb-aes-tegra",
+		.cra_priority = 300,
+		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+		.cra_blocksize = AES_BLOCK_SIZE,
+		.cra_alignmask = 3,
+		.cra_type = &crypto_ablkcipher_type,
+		.cra_u.ablkcipher = {
+			.min_keysize = AES_MIN_KEY_SIZE,
+			.max_keysize = AES_MAX_KEY_SIZE,
+			.ivsize = AES_MIN_KEY_SIZE,
+			.setkey = tegra_aes_setkey,
+			.encrypt = tegra_aes_ofb_encrypt,
+			.decrypt = tegra_aes_ofb_decrypt,
+		}
+	}, {
+		.cra_name = "ansi_cprng",
+		.cra_driver_name = "rng-aes-tegra",
+		.cra_flags = CRYPTO_ALG_TYPE_RNG,
+		.cra_ctxsize = sizeof(struct tegra_aes_ctx),
+		.cra_type = &crypto_rng_type,
+		.cra_u.rng = {
+			.rng_make_random = tegra_aes_get_random,
+			.rng_reset = tegra_aes_rng_reset,
+			.seedsize = AES_KEYSIZE_128 + (2 * DEFAULT_RNG_BLK_SZ),
+		}
+	}
+};
+
+static int tegra_aes_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_aes_dev *dd;
+	struct resource *res;
+	int err = -ENOMEM, i = 0, j;
+
+	dd = devm_kzalloc(dev, sizeof(struct tegra_aes_dev), GFP_KERNEL);
+	if (dd == NULL) {
+		dev_err(dev, "unable to alloc data struct.\n");
+		return err;
+	}
+
+	dd->dev = dev;
+	platform_set_drvdata(pdev, dd);
+
+	dd->slots = devm_kzalloc(dev, sizeof(struct tegra_aes_slot) *
+				 AES_NR_KEYSLOTS, GFP_KERNEL);
+	if (dd->slots == NULL) {
+		dev_err(dev, "unable to alloc slot struct.\n");
+		goto out;
+	}
+
+	spin_lock_init(&dd->lock);
+	crypto_init_queue(&dd->queue, TEGRA_AES_QUEUE_LENGTH);
+
+	/* Get the module base address */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "invalid resource type: base\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res),
+				     dev_name(&pdev->dev))) {
+		dev_err(&pdev->dev, "Couldn't request MEM resource\n");
+		return -ENODEV;
+	}
+
+	dd->io_base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!dd->io_base) {
+		dev_err(dev, "can't ioremap register space\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* Initialize the vde clock */
+	dd->aes_clk = clk_get(dev, "vde");
+	if (IS_ERR(dd->aes_clk)) {
+		dev_err(dev, "iclock intialization failed.\n");
+		err = -ENODEV;
+		goto out;
+	}
+
+	err = clk_set_rate(dd->aes_clk, ULONG_MAX);
+	if (err) {
+		dev_err(dd->dev, "iclk set_rate fail(%d)\n", err);
+		goto out;
+	}
+
+	/*
+	 * the foll contiguous memory is allocated as follows -
+	 * - hardware key table
+	 * - key schedule
+	 */
+	dd->ivkey_base = dma_alloc_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
+					    &dd->ivkey_phys_base,
+		GFP_KERNEL);
+	if (!dd->ivkey_base) {
+		dev_err(dev, "can not allocate iv/key buffer\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dd->buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+					&dd->dma_buf_in, GFP_KERNEL);
+	if (!dd->buf_in) {
+		dev_err(dev, "can not allocate dma-in buffer\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	dd->buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+					 &dd->dma_buf_out, GFP_KERNEL);
+	if (!dd->buf_out) {
+		dev_err(dev, "can not allocate dma-out buffer\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	init_completion(&dd->op_complete);
+	aes_wq = alloc_workqueue("tegra_aes_wq", WQ_HIGHPRI | WQ_UNBOUND, 1);
+	if (!aes_wq) {
+		dev_err(dev, "alloc_workqueue failed\n");
+		goto out;
+	}
+
+	/* get the irq */
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(dev, "invalid resource type: base\n");
+		err = -ENODEV;
+		goto out;
+	}
+	dd->irq = res->start;
+
+	err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH |
+				IRQF_SHARED, "tegra-aes", dd);
+	if (err) {
+		dev_err(dev, "request_irq failed\n");
+		goto out;
+	}
+
+	mutex_init(&aes_lock);
+	INIT_LIST_HEAD(&dev_list);
+
+	spin_lock_init(&list_lock);
+	spin_lock(&list_lock);
+	for (i = 0; i < AES_NR_KEYSLOTS; i++) {
+		if (i == SSK_SLOT_NUM)
+			continue;
+		dd->slots[i].slot_num = i;
+		INIT_LIST_HEAD(&dd->slots[i].node);
+		list_add_tail(&dd->slots[i].node, &dev_list);
+	}
+	spin_unlock(&list_lock);
+
+	aes_dev = dd;
+	for (i = 0; i < ARRAY_SIZE(algs); i++) {
+		INIT_LIST_HEAD(&algs[i].cra_list);
+
+		algs[i].cra_priority = 300;
+		algs[i].cra_ctxsize = sizeof(struct tegra_aes_ctx);
+		algs[i].cra_module = THIS_MODULE;
+		algs[i].cra_init = tegra_aes_cra_init;
+		algs[i].cra_exit = tegra_aes_cra_exit;
+
+		err = crypto_register_alg(&algs[i]);
+		if (err)
+			goto out;
+	}
+
+	dev_info(dev, "registered");
+	return 0;
+
+out:
+	for (j = 0; j < i; j++)
+		crypto_unregister_alg(&algs[j]);
+	if (dd->ivkey_base)
+		dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
+			dd->ivkey_base, dd->ivkey_phys_base);
+	if (dd->buf_in)
+		dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+			dd->buf_in, dd->dma_buf_in);
+	if (dd->buf_out)
+		dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+			dd->buf_out, dd->dma_buf_out);
+	if (IS_ERR(dd->aes_clk))
+		clk_put(dd->aes_clk);
+	if (aes_wq)
+		destroy_workqueue(aes_wq);
+	spin_lock(&list_lock);
+	list_del(&dev_list);
+	spin_unlock(&list_lock);
+
+	aes_dev = NULL;
+
+	dev_err(dev, "%s: initialization failed.\n", __func__);
+	return err;
+}
+
+static int __devexit tegra_aes_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_aes_dev *dd = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(algs); i++)
+		crypto_unregister_alg(&algs[i]);
+
+	cancel_work_sync(&aes_work);
+	destroy_workqueue(aes_wq);
+	spin_lock(&list_lock);
+	list_del(&dev_list);
+	spin_unlock(&list_lock);
+
+	dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES,
+			  dd->ivkey_base, dd->ivkey_phys_base);
+	dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+			  dd->buf_in, dd->dma_buf_in);
+	dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES,
+			  dd->buf_out, dd->dma_buf_out);
+	clk_put(dd->aes_clk);
+	aes_dev = NULL;
+
+	return 0;
+}
+
+static struct of_device_id tegra_aes_of_match[] __devinitdata = {
+	{ .compatible = "nvidia,tegra20-aes", },
+	{ .compatible = "nvidia,tegra30-aes", },
+	{ },
+};
+
+static struct platform_driver tegra_aes_driver = {
+	.probe  = tegra_aes_probe,
+	.remove = __devexit_p(tegra_aes_remove),
+	.driver = {
+		.name   = "tegra-aes",
+		.owner  = THIS_MODULE,
+		.of_match_table = tegra_aes_of_match,
+	},
+};
+
+module_platform_driver(tegra_aes_driver);
+
+MODULE_DESCRIPTION("Tegra AES/OFB/CPRNG hw acceleration support.");
+MODULE_AUTHOR("NVIDIA Corporation");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/tegra-aes.h b/drivers/crypto/tegra-aes.h
new file mode 100644
index 0000000..6006333
--- /dev/null
+++ b/drivers/crypto/tegra-aes.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __CRYPTODEV_TEGRA_AES_H
+#define __CRYPTODEV_TEGRA_AES_H
+
+#define TEGRA_AES_ICMDQUE_WR			0x1000
+#define TEGRA_AES_CMDQUE_CONTROL		0x1008
+#define TEGRA_AES_INTR_STATUS			0x1018
+#define TEGRA_AES_INT_ENB			0x1040
+#define TEGRA_AES_CONFIG			0x1044
+#define TEGRA_AES_IRAM_ACCESS_CFG		0x10A0
+#define TEGRA_AES_SECURE_DEST_ADDR		0x1100
+#define TEGRA_AES_SECURE_INPUT_SELECT		0x1104
+#define TEGRA_AES_SECURE_CONFIG			0x1108
+#define TEGRA_AES_SECURE_CONFIG_EXT		0x110C
+#define TEGRA_AES_SECURE_SECURITY		0x1110
+#define TEGRA_AES_SECURE_HASH_RESULT0		0x1120
+#define TEGRA_AES_SECURE_HASH_RESULT1		0x1124
+#define TEGRA_AES_SECURE_HASH_RESULT2		0x1128
+#define TEGRA_AES_SECURE_HASH_RESULT3		0x112C
+#define TEGRA_AES_SECURE_SEC_SEL0		0x1140
+#define TEGRA_AES_SECURE_SEC_SEL1		0x1144
+#define TEGRA_AES_SECURE_SEC_SEL2		0x1148
+#define TEGRA_AES_SECURE_SEC_SEL3		0x114C
+#define TEGRA_AES_SECURE_SEC_SEL4		0x1150
+#define TEGRA_AES_SECURE_SEC_SEL5		0x1154
+#define TEGRA_AES_SECURE_SEC_SEL6		0x1158
+#define TEGRA_AES_SECURE_SEC_SEL7		0x115C
+
+/* interrupt status reg masks and shifts */
+#define TEGRA_AES_ENGINE_BUSY_FIELD		BIT(0)
+#define TEGRA_AES_ICQ_EMPTY_FIELD		BIT(3)
+#define TEGRA_AES_DMA_BUSY_FIELD		BIT(23)
+
+/* secure select reg masks and shifts */
+#define TEGRA_AES_SECURE_SEL0_KEYREAD_ENB0_FIELD	BIT(0)
+
+/* secure config ext masks and shifts */
+#define TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD	BIT(15)
+
+/* secure config masks and shifts */
+#define TEGRA_AES_SECURE_KEY_INDEX_SHIFT	20
+#define TEGRA_AES_SECURE_KEY_INDEX_FIELD	(0x1F << TEGRA_AES_SECURE_KEY_INDEX_SHIFT)
+#define TEGRA_AES_SECURE_BLOCK_CNT_SHIFT	0
+#define TEGRA_AES_SECURE_BLOCK_CNT_FIELD	(0xFFFFF << TEGRA_AES_SECURE_BLOCK_CNT_SHIFT)
+
+/* stream interface select masks and shifts */
+#define TEGRA_AES_CMDQ_CTRL_UCMDQEN_FIELD	BIT(0)
+#define TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD	BIT(1)
+#define TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD	BIT(4)
+#define TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD	BIT(5)
+
+/* config register masks and shifts */
+#define TEGRA_AES_CONFIG_ENDIAN_ENB_FIELD	BIT(10)
+#define TEGRA_AES_CONFIG_MODE_SEL_SHIFT		0
+#define TEGRA_AES_CONFIG_MODE_SEL_FIELD		(0x1F << TEGRA_AES_CONFIG_MODE_SEL_SHIFT)
+
+/* extended config */
+#define TEGRA_AES_SECURE_OFFSET_CNT_SHIFT	24
+#define TEGRA_AES_SECURE_OFFSET_CNT_FIELD	(0xFF << TEGRA_AES_SECURE_OFFSET_CNT_SHIFT)
+#define TEGRA_AES_SECURE_KEYSCHED_GEN_FIELD	BIT(15)
+
+/* init vector select */
+#define TEGRA_AES_SECURE_IV_SELECT_SHIFT	10
+#define TEGRA_AES_SECURE_IV_SELECT_FIELD	BIT(10)
+
+/* secure engine input */
+#define TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT	28
+#define TEGRA_AES_SECURE_INPUT_ALG_SEL_FIELD	(0xF << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT)
+#define TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT	16
+#define TEGRA_AES_SECURE_INPUT_KEY_LEN_FIELD	(0xFFF << TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT)
+#define TEGRA_AES_SECURE_RNG_ENB_FIELD		BIT(11)
+#define TEGRA_AES_SECURE_CORE_SEL_SHIFT		9
+#define TEGRA_AES_SECURE_CORE_SEL_FIELD		BIT(9)
+#define TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT	7
+#define TEGRA_AES_SECURE_VCTRAM_SEL_FIELD	(0x3 << TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT)
+#define TEGRA_AES_SECURE_INPUT_SEL_SHIFT	5
+#define TEGRA_AES_SECURE_INPUT_SEL_FIELD	(0x3 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT)
+#define TEGRA_AES_SECURE_XOR_POS_SHIFT		3
+#define TEGRA_AES_SECURE_XOR_POS_FIELD		(0x3 << TEGRA_AES_SECURE_XOR_POS_SHIFT)
+#define TEGRA_AES_SECURE_HASH_ENB_FIELD		BIT(2)
+#define TEGRA_AES_SECURE_ON_THE_FLY_FIELD	BIT(0)
+
+/* interrupt error mask */
+#define TEGRA_AES_INT_ERROR_MASK		0xFFF000
+
+#endif
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index f1a2749..65c61db 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -201,7 +201,6 @@ config PL330_DMA
 	tristate "DMA API Driver for PL330"
 	select DMA_ENGINE
 	depends on ARM_AMBA
-	select PL330
 	help
 	  Select if your platform has one or more PL330 DMACs.
 	  You need to provide platform specific settings via
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b8ec03e..b0961d7 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -9,10 +9,15 @@
  * (at your option) any later version.
  */
 
+#include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/interrupt.h>
 #include <linux/amba/bus.h>
@@ -21,8 +26,266 @@
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 
+/*
+ * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req
+ * at 1byte/burst for P<->M and M<->M respectively.
+ * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req
+ * should be enough for P<->M and M<->M respectively.
+ */
+#define MCODE_BUFF_PER_REQ	256
+
+/* If the _pl330_req is available to the client */
+#define IS_FREE(req)	(*((u8 *)((req)->mc_cpu)) == CMD_DMAEND)
+
+/* Use this _only_ to wait on transient states */
+#define UNTIL(t, s)	while (!(_state(t) & (s))) cpu_relax();
+
+#ifdef PL330_DEBUG_MCGEN
+static unsigned cmd_line;
+#define PL330_DBGCMD_DUMP(off, x...)	do { \
+						printk("%x:", cmd_line); \
+						printk(x); \
+						cmd_line += off; \
+					} while (0)
+#define PL330_DBGMC_START(addr)		(cmd_line = addr)
+#else
+#define PL330_DBGCMD_DUMP(off, x...)	do {} while (0)
+#define PL330_DBGMC_START(addr)		do {} while (0)
+#endif
+
+/* The number of default descriptors */
 #define NR_DEFAULT_DESC	16
 
+/* Populated by the PL330 core driver for DMA API driver's info */
+struct pl330_config {
+	u32	periph_id;
+	u32	pcell_id;
+#define DMAC_MODE_NS	(1 << 0)
+	unsigned int	mode;
+	unsigned int	data_bus_width:10; /* In number of bits */
+	unsigned int	data_buf_dep:10;
+	unsigned int	num_chan:4;
+	unsigned int	num_peri:6;
+	u32		peri_ns;
+	unsigned int	num_events:6;
+	u32		irq_ns;
+};
+
+/* Handle to the DMAC provided to the PL330 core */
+struct pl330_info {
+	/* Owning device */
+	struct device *dev;
+	/* Size of MicroCode buffers for each channel. */
+	unsigned mcbufsz;
+	/* ioremap'ed address of PL330 registers. */
+	void __iomem	*base;
+	/* Client can freely use it. */
+	void	*client_data;
+	/* PL330 core data, Client must not touch it. */
+	void	*pl330_data;
+	/* Populated by the PL330 core driver during pl330_add */
+	struct pl330_config	pcfg;
+	/*
+	 * If the DMAC has some reset mechanism, then the
+	 * client may want to provide pointer to the method.
+	 */
+	void (*dmac_reset)(struct pl330_info *pi);
+};
+
+/**
+ * Request Configuration.
+ * The PL330 core does not modify this and uses the last
+ * working configuration if the request doesn't provide any.
+ *
+ * The Client may want to provide this info only for the
+ * first request and a request with new settings.
+ */
+struct pl330_reqcfg {
+	/* Address Incrementing */
+	unsigned dst_inc:1;
+	unsigned src_inc:1;
+
+	/*
+	 * For now, the SRC & DST protection levels
+	 * and burst size/length are assumed same.
+	 */
+	bool nonsecure;
+	bool privileged;
+	bool insnaccess;
+	unsigned brst_len:5;
+	unsigned brst_size:3; /* in power of 2 */
+
+	enum pl330_dstcachectrl dcctl;
+	enum pl330_srccachectrl scctl;
+	enum pl330_byteswap swap;
+	struct pl330_config *pcfg;
+};
+
+/*
+ * One cycle of DMAC operation.
+ * There may be more than one xfer in a request.
+ */
+struct pl330_xfer {
+	u32 src_addr;
+	u32 dst_addr;
+	/* Size to xfer */
+	u32 bytes;
+	/*
+	 * Pointer to next xfer in the list.
+	 * The last xfer in the req must point to NULL.
+	 */
+	struct pl330_xfer *next;
+};
+
+/* The xfer callbacks are made with one of these arguments. */
+enum pl330_op_err {
+	/* The all xfers in the request were success. */
+	PL330_ERR_NONE,
+	/* If req aborted due to global error. */
+	PL330_ERR_ABORT,
+	/* If req failed due to problem with Channel. */
+	PL330_ERR_FAIL,
+};
+
+/* A request defining Scatter-Gather List ending with NULL xfer. */
+struct pl330_req {
+	enum pl330_reqtype rqtype;
+	/* Index of peripheral for the xfer. */
+	unsigned peri:5;
+	/* Unique token for this xfer, set by the client. */
+	void *token;
+	/* Callback to be called after xfer. */
+	void (*xfer_cb)(void *token, enum pl330_op_err err);
+	/* If NULL, req will be done at last set parameters. */
+	struct pl330_reqcfg *cfg;
+	/* Pointer to first xfer in the request. */
+	struct pl330_xfer *x;
+};
+
+/*
+ * To know the status of the channel and DMAC, the client
+ * provides a pointer to this structure. The PL330 core
+ * fills it with current information.
+ */
+struct pl330_chanstatus {
+	/*
+	 * If the DMAC engine halted due to some error,
+	 * the client should remove-add DMAC.
+	 */
+	bool dmac_halted;
+	/*
+	 * If channel is halted due to some error,
+	 * the client should ABORT/FLUSH and START the channel.
+	 */
+	bool faulting;
+	/* Location of last load */
+	u32 src_addr;
+	/* Location of last store */
+	u32 dst_addr;
+	/*
+	 * Pointer to the currently active req, NULL if channel is
+	 * inactive, even though the requests may be present.
+	 */
+	struct pl330_req *top_req;
+	/* Pointer to req waiting second in the queue if any. */
+	struct pl330_req *wait_req;
+};
+
+enum pl330_chan_op {
+	/* Start the channel */
+	PL330_OP_START,
+	/* Abort the active xfer */
+	PL330_OP_ABORT,
+	/* Stop xfer and flush queue */
+	PL330_OP_FLUSH,
+};
+
+struct _xfer_spec {
+	u32 ccr;
+	struct pl330_req *r;
+	struct pl330_xfer *x;
+};
+
+enum dmamov_dst {
+	SAR = 0,
+	CCR,
+	DAR,
+};
+
+enum pl330_dst {
+	SRC = 0,
+	DST,
+};
+
+enum pl330_cond {
+	SINGLE,
+	BURST,
+	ALWAYS,
+};
+
+struct _pl330_req {
+	u32 mc_bus;
+	void *mc_cpu;
+	/* Number of bytes taken to setup MC for the req */
+	u32 mc_len;
+	struct pl330_req *r;
+	/* Hook to attach to DMAC's list of reqs with due callback */
+	struct list_head rqd;
+};
+
+/* ToBeDone for tasklet */
+struct _pl330_tbd {
+	bool reset_dmac;
+	bool reset_mngr;
+	u8 reset_chan;
+};
+
+/* A DMAC Thread */
+struct pl330_thread {
+	u8 id;
+	int ev;
+	/* If the channel is not yet acquired by any client */
+	bool free;
+	/* Parent DMAC */
+	struct pl330_dmac *dmac;
+	/* Only two at a time */
+	struct _pl330_req req[2];
+	/* Index of the last enqueued request */
+	unsigned lstenq;
+	/* Index of the last submitted request or -1 if the DMA is stopped */
+	int req_running;
+};
+
+enum pl330_dmac_state {
+	UNINIT,
+	INIT,
+	DYING,
+};
+
+/* A DMAC */
+struct pl330_dmac {
+	spinlock_t		lock;
+	/* Holds list of reqs with due callbacks */
+	struct list_head	req_done;
+	/* Pointer to platform specific stuff */
+	struct pl330_info	*pinfo;
+	/* Maximum possible events/irqs */
+	int			events[32];
+	/* BUS address of MicroCode buffer */
+	u32			mcode_bus;
+	/* CPU address of MicroCode buffer */
+	void			*mcode_cpu;
+	/* List of all Channel threads */
+	struct pl330_thread	*channels;
+	/* Pointer to the MANAGER thread */
+	struct pl330_thread	*manager;
+	/* To handle bad news in interrupt */
+	struct tasklet_struct	tasks;
+	struct _pl330_tbd	dmac_tbd;
+	/* State of DMAC operation */
+	enum pl330_dmac_state	state;
+};
+
 enum desc_status {
 	/* In the DMAC pool */
 	FREE,
@@ -117,6 +380,1592 @@ struct dma_pl330_desc {
 	struct dma_pl330_chan *pchan;
 };
 
+static inline void _callback(struct pl330_req *r, enum pl330_op_err err)
+{
+	if (r && r->xfer_cb)
+		r->xfer_cb(r->token, err);
+}
+
+static inline bool _queue_empty(struct pl330_thread *thrd)
+{
+	return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1]))
+		? true : false;
+}
+
+static inline bool _queue_full(struct pl330_thread *thrd)
+{
+	return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1]))
+		? false : true;
+}
+
+static inline bool is_manager(struct pl330_thread *thrd)
+{
+	struct pl330_dmac *pl330 = thrd->dmac;
+
+	/* MANAGER is indexed at the end */
+	if (thrd->id == pl330->pinfo->pcfg.num_chan)
+		return true;
+	else
+		return false;
+}
+
+/* If manager of the thread is in Non-Secure mode */
+static inline bool _manager_ns(struct pl330_thread *thrd)
+{
+	struct pl330_dmac *pl330 = thrd->dmac;
+
+	return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false;
+}
+
+static inline u32 get_id(struct pl330_info *pi, u32 off)
+{
+	void __iomem *regs = pi->base;
+	u32 id = 0;
+
+	id |= (readb(regs + off + 0x0) << 0);
+	id |= (readb(regs + off + 0x4) << 8);
+	id |= (readb(regs + off + 0x8) << 16);
+	id |= (readb(regs + off + 0xc) << 24);
+
+	return id;
+}
+
+static inline u32 get_revision(u32 periph_id)
+{
+	return (periph_id >> PERIPH_REV_SHIFT) & PERIPH_REV_MASK;
+}
+
+static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[],
+		enum pl330_dst da, u16 val)
+{
+	if (dry_run)
+		return SZ_DMAADDH;
+
+	buf[0] = CMD_DMAADDH;
+	buf[0] |= (da << 1);
+	*((u16 *)&buf[1]) = val;
+
+	PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
+		da == 1 ? "DA" : "SA", val);
+
+	return SZ_DMAADDH;
+}
+
+static inline u32 _emit_END(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMAEND;
+
+	buf[0] = CMD_DMAEND;
+
+	PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n");
+
+	return SZ_DMAEND;
+}
+
+static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri)
+{
+	if (dry_run)
+		return SZ_DMAFLUSHP;
+
+	buf[0] = CMD_DMAFLUSHP;
+
+	peri &= 0x1f;
+	peri <<= 3;
+	buf[1] = peri;
+
+	PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3);
+
+	return SZ_DMAFLUSHP;
+}
+
+static inline u32 _emit_LD(unsigned dry_run, u8 buf[],	enum pl330_cond cond)
+{
+	if (dry_run)
+		return SZ_DMALD;
+
+	buf[0] = CMD_DMALD;
+
+	if (cond == SINGLE)
+		buf[0] |= (0 << 1) | (1 << 0);
+	else if (cond == BURST)
+		buf[0] |= (1 << 1) | (1 << 0);
+
+	PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n",
+		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
+
+	return SZ_DMALD;
+}
+
+static inline u32 _emit_LDP(unsigned dry_run, u8 buf[],
+		enum pl330_cond cond, u8 peri)
+{
+	if (dry_run)
+		return SZ_DMALDP;
+
+	buf[0] = CMD_DMALDP;
+
+	if (cond == BURST)
+		buf[0] |= (1 << 1);
+
+	peri &= 0x1f;
+	peri <<= 3;
+	buf[1] = peri;
+
+	PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n",
+		cond == SINGLE ? 'S' : 'B', peri >> 3);
+
+	return SZ_DMALDP;
+}
+
+static inline u32 _emit_LP(unsigned dry_run, u8 buf[],
+		unsigned loop, u8 cnt)
+{
+	if (dry_run)
+		return SZ_DMALP;
+
+	buf[0] = CMD_DMALP;
+
+	if (loop)
+		buf[0] |= (1 << 1);
+
+	cnt--; /* DMAC increments by 1 internally */
+	buf[1] = cnt;
+
+	PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt);
+
+	return SZ_DMALP;
+}
+
+struct _arg_LPEND {
+	enum pl330_cond cond;
+	bool forever;
+	unsigned loop;
+	u8 bjump;
+};
+
+static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[],
+		const struct _arg_LPEND *arg)
+{
+	enum pl330_cond cond = arg->cond;
+	bool forever = arg->forever;
+	unsigned loop = arg->loop;
+	u8 bjump = arg->bjump;
+
+	if (dry_run)
+		return SZ_DMALPEND;
+
+	buf[0] = CMD_DMALPEND;
+
+	if (loop)
+		buf[0] |= (1 << 2);
+
+	if (!forever)
+		buf[0] |= (1 << 4);
+
+	if (cond == SINGLE)
+		buf[0] |= (0 << 1) | (1 << 0);
+	else if (cond == BURST)
+		buf[0] |= (1 << 1) | (1 << 0);
+
+	buf[1] = bjump;
+
+	PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n",
+			forever ? "FE" : "END",
+			cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'),
+			loop ? '1' : '0',
+			bjump);
+
+	return SZ_DMALPEND;
+}
+
+static inline u32 _emit_KILL(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMAKILL;
+
+	buf[0] = CMD_DMAKILL;
+
+	return SZ_DMAKILL;
+}
+
+static inline u32 _emit_MOV(unsigned dry_run, u8 buf[],
+		enum dmamov_dst dst, u32 val)
+{
+	if (dry_run)
+		return SZ_DMAMOV;
+
+	buf[0] = CMD_DMAMOV;
+	buf[1] = dst;
+	*((u32 *)&buf[2]) = val;
+
+	PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
+		dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
+
+	return SZ_DMAMOV;
+}
+
+static inline u32 _emit_NOP(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMANOP;
+
+	buf[0] = CMD_DMANOP;
+
+	PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n");
+
+	return SZ_DMANOP;
+}
+
+static inline u32 _emit_RMB(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMARMB;
+
+	buf[0] = CMD_DMARMB;
+
+	PL330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n");
+
+	return SZ_DMARMB;
+}
+
+static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev)
+{
+	if (dry_run)
+		return SZ_DMASEV;
+
+	buf[0] = CMD_DMASEV;
+
+	ev &= 0x1f;
+	ev <<= 3;
+	buf[1] = ev;
+
+	PL330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3);
+
+	return SZ_DMASEV;
+}
+
+static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum pl330_cond cond)
+{
+	if (dry_run)
+		return SZ_DMAST;
+
+	buf[0] = CMD_DMAST;
+
+	if (cond == SINGLE)
+		buf[0] |= (0 << 1) | (1 << 0);
+	else if (cond == BURST)
+		buf[0] |= (1 << 1) | (1 << 0);
+
+	PL330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n",
+		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'));
+
+	return SZ_DMAST;
+}
+
+static inline u32 _emit_STP(unsigned dry_run, u8 buf[],
+		enum pl330_cond cond, u8 peri)
+{
+	if (dry_run)
+		return SZ_DMASTP;
+
+	buf[0] = CMD_DMASTP;
+
+	if (cond == BURST)
+		buf[0] |= (1 << 1);
+
+	peri &= 0x1f;
+	peri <<= 3;
+	buf[1] = peri;
+
+	PL330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n",
+		cond == SINGLE ? 'S' : 'B', peri >> 3);
+
+	return SZ_DMASTP;
+}
+
+static inline u32 _emit_STZ(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMASTZ;
+
+	buf[0] = CMD_DMASTZ;
+
+	PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n");
+
+	return SZ_DMASTZ;
+}
+
+static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev,
+		unsigned invalidate)
+{
+	if (dry_run)
+		return SZ_DMAWFE;
+
+	buf[0] = CMD_DMAWFE;
+
+	ev &= 0x1f;
+	ev <<= 3;
+	buf[1] = ev;
+
+	if (invalidate)
+		buf[1] |= (1 << 1);
+
+	PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n",
+		ev >> 3, invalidate ? ", I" : "");
+
+	return SZ_DMAWFE;
+}
+
+static inline u32 _emit_WFP(unsigned dry_run, u8 buf[],
+		enum pl330_cond cond, u8 peri)
+{
+	if (dry_run)
+		return SZ_DMAWFP;
+
+	buf[0] = CMD_DMAWFP;
+
+	if (cond == SINGLE)
+		buf[0] |= (0 << 1) | (0 << 0);
+	else if (cond == BURST)
+		buf[0] |= (1 << 1) | (0 << 0);
+	else
+		buf[0] |= (0 << 1) | (1 << 0);
+
+	peri &= 0x1f;
+	peri <<= 3;
+	buf[1] = peri;
+
+	PL330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n",
+		cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3);
+
+	return SZ_DMAWFP;
+}
+
+static inline u32 _emit_WMB(unsigned dry_run, u8 buf[])
+{
+	if (dry_run)
+		return SZ_DMAWMB;
+
+	buf[0] = CMD_DMAWMB;
+
+	PL330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n");
+
+	return SZ_DMAWMB;
+}
+
+struct _arg_GO {
+	u8 chan;
+	u32 addr;
+	unsigned ns;
+};
+
+static inline u32 _emit_GO(unsigned dry_run, u8 buf[],
+		const struct _arg_GO *arg)
+{
+	u8 chan = arg->chan;
+	u32 addr = arg->addr;
+	unsigned ns = arg->ns;
+
+	if (dry_run)
+		return SZ_DMAGO;
+
+	buf[0] = CMD_DMAGO;
+	buf[0] |= (ns << 1);
+
+	buf[1] = chan & 0x7;
+
+	*((u32 *)&buf[2]) = addr;
+
+	return SZ_DMAGO;
+}
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+/* Returns Time-Out */
+static bool _until_dmac_idle(struct pl330_thread *thrd)
+{
+	void __iomem *regs = thrd->dmac->pinfo->base;
+	unsigned long loops = msecs_to_loops(5);
+
+	do {
+		/* Until Manager is Idle */
+		if (!(readl(regs + DBGSTATUS) & DBG_BUSY))
+			break;
+
+		cpu_relax();
+	} while (--loops);
+
+	if (!loops)
+		return true;
+
+	return false;
+}
+
+static inline void _execute_DBGINSN(struct pl330_thread *thrd,
+		u8 insn[], bool as_manager)
+{
+	void __iomem *regs = thrd->dmac->pinfo->base;
+	u32 val;
+
+	val = (insn[0] << 16) | (insn[1] << 24);
+	if (!as_manager) {
+		val |= (1 << 0);
+		val |= (thrd->id << 8); /* Channel Number */
+	}
+	writel(val, regs + DBGINST0);
+
+	val = *((u32 *)&insn[2]);
+	writel(val, regs + DBGINST1);
+
+	/* If timed out due to halted state-machine */
+	if (_until_dmac_idle(thrd)) {
+		dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n");
+		return;
+	}
+
+	/* Get going */
+	writel(0, regs + DBGCMD);
+}
+
+/*
+ * Mark a _pl330_req as free.
+ * We do it by writing DMAEND as the first instruction
+ * because no valid request is going to have DMAEND as
+ * its first instruction to execute.
+ */
+static void mark_free(struct pl330_thread *thrd, int idx)
+{
+	struct _pl330_req *req = &thrd->req[idx];
+
+	_emit_END(0, req->mc_cpu);
+	req->mc_len = 0;
+
+	thrd->req_running = -1;
+}
+
+static inline u32 _state(struct pl330_thread *thrd)
+{
+	void __iomem *regs = thrd->dmac->pinfo->base;
+	u32 val;
+
+	if (is_manager(thrd))
+		val = readl(regs + DS) & 0xf;
+	else
+		val = readl(regs + CS(thrd->id)) & 0xf;
+
+	switch (val) {
+	case DS_ST_STOP:
+		return PL330_STATE_STOPPED;
+	case DS_ST_EXEC:
+		return PL330_STATE_EXECUTING;
+	case DS_ST_CMISS:
+		return PL330_STATE_CACHEMISS;
+	case DS_ST_UPDTPC:
+		return PL330_STATE_UPDTPC;
+	case DS_ST_WFE:
+		return PL330_STATE_WFE;
+	case DS_ST_FAULT:
+		return PL330_STATE_FAULTING;
+	case DS_ST_ATBRR:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_ATBARRIER;
+	case DS_ST_QBUSY:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_QUEUEBUSY;
+	case DS_ST_WFP:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_WFP;
+	case DS_ST_KILL:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_KILLING;
+	case DS_ST_CMPLT:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_COMPLETING;
+	case DS_ST_FLTCMP:
+		if (is_manager(thrd))
+			return PL330_STATE_INVALID;
+		else
+			return PL330_STATE_FAULT_COMPLETING;
+	default:
+		return PL330_STATE_INVALID;
+	}
+}
+
+static void _stop(struct pl330_thread *thrd)
+{
+	void __iomem *regs = thrd->dmac->pinfo->base;
+	u8 insn[6] = {0, 0, 0, 0, 0, 0};
+
+	if (_state(thrd) == PL330_STATE_FAULT_COMPLETING)
+		UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+	/* Return if nothing needs to be done */
+	if (_state(thrd) == PL330_STATE_COMPLETING
+		  || _state(thrd) == PL330_STATE_KILLING
+		  || _state(thrd) == PL330_STATE_STOPPED)
+		return;
+
+	_emit_KILL(0, insn);
+
+	/* Stop generating interrupts for SEV */
+	writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
+
+	_execute_DBGINSN(thrd, insn, is_manager(thrd));
+}
+
+/* Start doing req 'idx' of thread 'thrd' */
+static bool _trigger(struct pl330_thread *thrd)
+{
+	void __iomem *regs = thrd->dmac->pinfo->base;
+	struct _pl330_req *req;
+	struct pl330_req *r;
+	struct _arg_GO go;
+	unsigned ns;
+	u8 insn[6] = {0, 0, 0, 0, 0, 0};
+	int idx;
+
+	/* Return if already ACTIVE */
+	if (_state(thrd) != PL330_STATE_STOPPED)
+		return true;
+
+	idx = 1 - thrd->lstenq;
+	if (!IS_FREE(&thrd->req[idx]))
+		req = &thrd->req[idx];
+	else {
+		idx = thrd->lstenq;
+		if (!IS_FREE(&thrd->req[idx]))
+			req = &thrd->req[idx];
+		else
+			req = NULL;
+	}
+
+	/* Return if no request */
+	if (!req || !req->r)
+		return true;
+
+	r = req->r;
+
+	if (r->cfg)
+		ns = r->cfg->nonsecure ? 1 : 0;
+	else if (readl(regs + CS(thrd->id)) & CS_CNS)
+		ns = 1;
+	else
+		ns = 0;
+
+	/* See 'Abort Sources' point-4 at Page 2-25 */
+	if (_manager_ns(thrd) && !ns)
+		dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n",
+			__func__, __LINE__);
+
+	go.chan = thrd->id;
+	go.addr = req->mc_bus;
+	go.ns = ns;
+	_emit_GO(0, insn, &go);
+
+	/* Set to generate interrupts for SEV */
+	writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
+
+	/* Only manager can execute GO */
+	_execute_DBGINSN(thrd, insn, true);
+
+	thrd->req_running = idx;
+
+	return true;
+}
+
+static bool _start(struct pl330_thread *thrd)
+{
+	switch (_state(thrd)) {
+	case PL330_STATE_FAULT_COMPLETING:
+		UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING);
+
+		if (_state(thrd) == PL330_STATE_KILLING)
+			UNTIL(thrd, PL330_STATE_STOPPED)
+
+	case PL330_STATE_FAULTING:
+		_stop(thrd);
+
+	case PL330_STATE_KILLING:
+	case PL330_STATE_COMPLETING:
+		UNTIL(thrd, PL330_STATE_STOPPED)
+
+	case PL330_STATE_STOPPED:
+		return _trigger(thrd);
+
+	case PL330_STATE_WFP:
+	case PL330_STATE_QUEUEBUSY:
+	case PL330_STATE_ATBARRIER:
+	case PL330_STATE_UPDTPC:
+	case PL330_STATE_CACHEMISS:
+	case PL330_STATE_EXECUTING:
+		return true;
+
+	case PL330_STATE_WFE: /* For RESUME, nothing yet */
+	default:
+		return false;
+	}
+}
+
+static inline int _ldst_memtomem(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
+{
+	int off = 0;
+	struct pl330_config *pcfg = pxs->r->cfg->pcfg;
+
+	/* check lock-up free version */
+	if (get_revision(pcfg->periph_id) >= PERIPH_REV_R1P0) {
+		while (cyc--) {
+			off += _emit_LD(dry_run, &buf[off], ALWAYS);
+			off += _emit_ST(dry_run, &buf[off], ALWAYS);
+		}
+	} else {
+		while (cyc--) {
+			off += _emit_LD(dry_run, &buf[off], ALWAYS);
+			off += _emit_RMB(dry_run, &buf[off]);
+			off += _emit_ST(dry_run, &buf[off], ALWAYS);
+			off += _emit_WMB(dry_run, &buf[off]);
+		}
+	}
+
+	return off;
+}
+
+static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
+{
+	int off = 0;
+
+	while (cyc--) {
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_ST(dry_run, &buf[off], ALWAYS);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+	}
+
+	return off;
+}
+
+static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
+{
+	int off = 0;
+
+	while (cyc--) {
+		off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_LD(dry_run, &buf[off], ALWAYS);
+		off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri);
+		off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri);
+	}
+
+	return off;
+}
+
+static int _bursts(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs, int cyc)
+{
+	int off = 0;
+
+	switch (pxs->r->rqtype) {
+	case MEMTODEV:
+		off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc);
+		break;
+	case DEVTOMEM:
+		off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc);
+		break;
+	case MEMTOMEM:
+		off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc);
+		break;
+	default:
+		off += 0x40000000; /* Scare off the Client */
+		break;
+	}
+
+	return off;
+}
+
+/* Returns bytes consumed and updates bursts */
+static inline int _loop(unsigned dry_run, u8 buf[],
+		unsigned long *bursts, const struct _xfer_spec *pxs)
+{
+	int cyc, cycmax, szlp, szlpend, szbrst, off;
+	unsigned lcnt0, lcnt1, ljmp0, ljmp1;
+	struct _arg_LPEND lpend;
+
+	/* Max iterations possible in DMALP is 256 */
+	if (*bursts >= 256*256) {
+		lcnt1 = 256;
+		lcnt0 = 256;
+		cyc = *bursts / lcnt1 / lcnt0;
+	} else if (*bursts > 256) {
+		lcnt1 = 256;
+		lcnt0 = *bursts / lcnt1;
+		cyc = 1;
+	} else {
+		lcnt1 = *bursts;
+		lcnt0 = 0;
+		cyc = 1;
+	}
+
+	szlp = _emit_LP(1, buf, 0, 0);
+	szbrst = _bursts(1, buf, pxs, 1);
+
+	lpend.cond = ALWAYS;
+	lpend.forever = false;
+	lpend.loop = 0;
+	lpend.bjump = 0;
+	szlpend = _emit_LPEND(1, buf, &lpend);
+
+	if (lcnt0) {
+		szlp *= 2;
+		szlpend *= 2;
+	}
+
+	/*
+	 * Max bursts that we can unroll due to limit on the
+	 * size of backward jump that can be encoded in DMALPEND
+	 * which is 8-bits and hence 255
+	 */
+	cycmax = (255 - (szlp + szlpend)) / szbrst;
+
+	cyc = (cycmax < cyc) ? cycmax : cyc;
+
+	off = 0;
+
+	if (lcnt0) {
+		off += _emit_LP(dry_run, &buf[off], 0, lcnt0);
+		ljmp0 = off;
+	}
+
+	off += _emit_LP(dry_run, &buf[off], 1, lcnt1);
+	ljmp1 = off;
+
+	off += _bursts(dry_run, &buf[off], pxs, cyc);
+
+	lpend.cond = ALWAYS;
+	lpend.forever = false;
+	lpend.loop = 1;
+	lpend.bjump = off - ljmp1;
+	off += _emit_LPEND(dry_run, &buf[off], &lpend);
+
+	if (lcnt0) {
+		lpend.cond = ALWAYS;
+		lpend.forever = false;
+		lpend.loop = 0;
+		lpend.bjump = off - ljmp0;
+		off += _emit_LPEND(dry_run, &buf[off], &lpend);
+	}
+
+	*bursts = lcnt1 * cyc;
+	if (lcnt0)
+		*bursts *= lcnt0;
+
+	return off;
+}
+
+static inline int _setup_loops(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs)
+{
+	struct pl330_xfer *x = pxs->x;
+	u32 ccr = pxs->ccr;
+	unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr);
+	int off = 0;
+
+	while (bursts) {
+		c = bursts;
+		off += _loop(dry_run, &buf[off], &c, pxs);
+		bursts -= c;
+	}
+
+	return off;
+}
+
+static inline int _setup_xfer(unsigned dry_run, u8 buf[],
+		const struct _xfer_spec *pxs)
+{
+	struct pl330_xfer *x = pxs->x;
+	int off = 0;
+
+	/* DMAMOV SAR, x->src_addr */
+	off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr);
+	/* DMAMOV DAR, x->dst_addr */
+	off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr);
+
+	/* Setup Loop(s) */
+	off += _setup_loops(dry_run, &buf[off], pxs);
+
+	return off;
+}
+
+/*
+ * A req is a sequence of one or more xfer units.
+ * Returns the number of bytes taken to setup the MC for the req.
+ */
+static int _setup_req(unsigned dry_run, struct pl330_thread *thrd,
+		unsigned index, struct _xfer_spec *pxs)
+{
+	struct _pl330_req *req = &thrd->req[index];
+	struct pl330_xfer *x;
+	u8 *buf = req->mc_cpu;
+	int off = 0;
+
+	PL330_DBGMC_START(req->mc_bus);
+
+	/* DMAMOV CCR, ccr */
+	off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr);
+
+	x = pxs->r->x;
+	do {
+		/* Error if xfer length is not aligned at burst size */
+		if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr)))
+			return -EINVAL;
+
+		pxs->x = x;
+		off += _setup_xfer(dry_run, &buf[off], pxs);
+
+		x = x->next;
+	} while (x);
+
+	/* DMASEV peripheral/event */
+	off += _emit_SEV(dry_run, &buf[off], thrd->ev);
+	/* DMAEND */
+	off += _emit_END(dry_run, &buf[off]);
+
+	return off;
+}
+
+static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
+{
+	u32 ccr = 0;
+
+	if (rqc->src_inc)
+		ccr |= CC_SRCINC;
+
+	if (rqc->dst_inc)
+		ccr |= CC_DSTINC;
+
+	/* We set same protection levels for Src and DST for now */
+	if (rqc->privileged)
+		ccr |= CC_SRCPRI | CC_DSTPRI;
+	if (rqc->nonsecure)
+		ccr |= CC_SRCNS | CC_DSTNS;
+	if (rqc->insnaccess)
+		ccr |= CC_SRCIA | CC_DSTIA;
+
+	ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT);
+	ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT);
+
+	ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
+	ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
+
+	ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT);
+	ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT);
+
+	ccr |= (rqc->swap << CC_SWAP_SHFT);
+
+	return ccr;
+}
+
+static inline bool _is_valid(u32 ccr)
+{
+	enum pl330_dstcachectrl dcctl;
+	enum pl330_srccachectrl scctl;
+
+	dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK;
+	scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK;
+
+	if (dcctl == DINVALID1 || dcctl == DINVALID2
+			|| scctl == SINVALID1 || scctl == SINVALID2)
+		return false;
+	else
+		return true;
+}
+
+/*
+ * Submit a list of xfers after which the client wants notification.
+ * Client is not notified after each xfer unit, just once after all
+ * xfer units are done or some error occurs.
+ */
+static int pl330_submit_req(void *ch_id, struct pl330_req *r)
+{
+	struct pl330_thread *thrd = ch_id;
+	struct pl330_dmac *pl330;
+	struct pl330_info *pi;
+	struct _xfer_spec xs;
+	unsigned long flags;
+	void __iomem *regs;
+	unsigned idx;
+	u32 ccr;
+	int ret = 0;
+
+	/* No Req or Unacquired Channel or DMAC */
+	if (!r || !thrd || thrd->free)
+		return -EINVAL;
+
+	pl330 = thrd->dmac;
+	pi = pl330->pinfo;
+	regs = pi->base;
+
+	if (pl330->state == DYING
+		|| pl330->dmac_tbd.reset_chan & (1 << thrd->id)) {
+		dev_info(thrd->dmac->pinfo->dev, "%s:%d\n",
+			__func__, __LINE__);
+		return -EAGAIN;
+	}
+
+	/* If request for non-existing peripheral */
+	if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) {
+		dev_info(thrd->dmac->pinfo->dev,
+				"%s:%d Invalid peripheral(%u)!\n",
+				__func__, __LINE__, r->peri);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pl330->lock, flags);
+
+	if (_queue_full(thrd)) {
+		ret = -EAGAIN;
+		goto xfer_exit;
+	}
+
+	/* Prefer Secure Channel */
+	if (!_manager_ns(thrd))
+		r->cfg->nonsecure = 0;
+	else
+		r->cfg->nonsecure = 1;
+
+	/* Use last settings, if not provided */
+	if (r->cfg)
+		ccr = _prepare_ccr(r->cfg);
+	else
+		ccr = readl(regs + CC(thrd->id));
+
+	/* If this req doesn't have valid xfer settings */
+	if (!_is_valid(ccr)) {
+		ret = -EINVAL;
+		dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n",
+			__func__, __LINE__, ccr);
+		goto xfer_exit;
+	}
+
+	idx = IS_FREE(&thrd->req[0]) ? 0 : 1;
+
+	xs.ccr = ccr;
+	xs.r = r;
+
+	/* First dry run to check if req is acceptable */
+	ret = _setup_req(1, thrd, idx, &xs);
+	if (ret < 0)
+		goto xfer_exit;
+
+	if (ret > pi->mcbufsz / 2) {
+		dev_info(thrd->dmac->pinfo->dev,
+			"%s:%d Trying increasing mcbufsz\n",
+				__func__, __LINE__);
+		ret = -ENOMEM;
+		goto xfer_exit;
+	}
+
+	/* Hook the request */
+	thrd->lstenq = idx;
+	thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs);
+	thrd->req[idx].r = r;
+
+	ret = 0;
+
+xfer_exit:
+	spin_unlock_irqrestore(&pl330->lock, flags);
+
+	return ret;
+}
+
+static void pl330_dotask(unsigned long data)
+{
+	struct pl330_dmac *pl330 = (struct pl330_dmac *) data;
+	struct pl330_info *pi = pl330->pinfo;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+
+	/* The DMAC itself gone nuts */
+	if (pl330->dmac_tbd.reset_dmac) {
+		pl330->state = DYING;
+		/* Reset the manager too */
+		pl330->dmac_tbd.reset_mngr = true;
+		/* Clear the reset flag */
+		pl330->dmac_tbd.reset_dmac = false;
+	}
+
+	if (pl330->dmac_tbd.reset_mngr) {
+		_stop(pl330->manager);
+		/* Reset all channels */
+		pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1;
+		/* Clear the reset flag */
+		pl330->dmac_tbd.reset_mngr = false;
+	}
+
+	for (i = 0; i < pi->pcfg.num_chan; i++) {
+
+		if (pl330->dmac_tbd.reset_chan & (1 << i)) {
+			struct pl330_thread *thrd = &pl330->channels[i];
+			void __iomem *regs = pi->base;
+			enum pl330_op_err err;
+
+			_stop(thrd);
+
+			if (readl(regs + FSC) & (1 << thrd->id))
+				err = PL330_ERR_FAIL;
+			else
+				err = PL330_ERR_ABORT;
+
+			spin_unlock_irqrestore(&pl330->lock, flags);
+
+			_callback(thrd->req[1 - thrd->lstenq].r, err);
+			_callback(thrd->req[thrd->lstenq].r, err);
+
+			spin_lock_irqsave(&pl330->lock, flags);
+
+			thrd->req[0].r = NULL;
+			thrd->req[1].r = NULL;
+			mark_free(thrd, 0);
+			mark_free(thrd, 1);
+
+			/* Clear the reset flag */
+			pl330->dmac_tbd.reset_chan &= ~(1 << i);
+		}
+	}
+
+	spin_unlock_irqrestore(&pl330->lock, flags);
+
+	return;
+}
+
+/* Returns 1 if state was updated, 0 otherwise */
+static int pl330_update(const struct pl330_info *pi)
+{
+	struct _pl330_req *rqdone;
+	struct pl330_dmac *pl330;
+	unsigned long flags;
+	void __iomem *regs;
+	u32 val;
+	int id, ev, ret = 0;
+
+	if (!pi || !pi->pl330_data)
+		return 0;
+
+	regs = pi->base;
+	pl330 = pi->pl330_data;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+
+	val = readl(regs + FSM) & 0x1;
+	if (val)
+		pl330->dmac_tbd.reset_mngr = true;
+	else
+		pl330->dmac_tbd.reset_mngr = false;
+
+	val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
+	pl330->dmac_tbd.reset_chan |= val;
+	if (val) {
+		int i = 0;
+		while (i < pi->pcfg.num_chan) {
+			if (val & (1 << i)) {
+				dev_info(pi->dev,
+					"Reset Channel-%d\t CS-%x FTC-%x\n",
+						i, readl(regs + CS(i)),
+						readl(regs + FTC(i)));
+				_stop(&pl330->channels[i]);
+			}
+			i++;
+		}
+	}
+
+	/* Check which event happened i.e, thread notified */
+	val = readl(regs + ES);
+	if (pi->pcfg.num_events < 32
+			&& val & ~((1 << pi->pcfg.num_events) - 1)) {
+		pl330->dmac_tbd.reset_dmac = true;
+		dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__);
+		ret = 1;
+		goto updt_exit;
+	}
+
+	for (ev = 0; ev < pi->pcfg.num_events; ev++) {
+		if (val & (1 << ev)) { /* Event occurred */
+			struct pl330_thread *thrd;
+			u32 inten = readl(regs + INTEN);
+			int active;
+
+			/* Clear the event */
+			if (inten & (1 << ev))
+				writel(1 << ev, regs + INTCLR);
+
+			ret = 1;
+
+			id = pl330->events[ev];
+
+			thrd = &pl330->channels[id];
+
+			active = thrd->req_running;
+			if (active == -1) /* Aborted */
+				continue;
+
+			rqdone = &thrd->req[active];
+			mark_free(thrd, active);
+
+			/* Get going again ASAP */
+			_start(thrd);
+
+			/* For now, just make a list of callbacks to be done */
+			list_add_tail(&rqdone->rqd, &pl330->req_done);
+		}
+	}
+
+	/* Now that we are in no hurry, do the callbacks */
+	while (!list_empty(&pl330->req_done)) {
+		struct pl330_req *r;
+
+		rqdone = container_of(pl330->req_done.next,
+					struct _pl330_req, rqd);
+
+		list_del_init(&rqdone->rqd);
+
+		/* Detach the req */
+		r = rqdone->r;
+		rqdone->r = NULL;
+
+		spin_unlock_irqrestore(&pl330->lock, flags);
+		_callback(r, PL330_ERR_NONE);
+		spin_lock_irqsave(&pl330->lock, flags);
+	}
+
+updt_exit:
+	spin_unlock_irqrestore(&pl330->lock, flags);
+
+	if (pl330->dmac_tbd.reset_dmac
+			|| pl330->dmac_tbd.reset_mngr
+			|| pl330->dmac_tbd.reset_chan) {
+		ret = 1;
+		tasklet_schedule(&pl330->tasks);
+	}
+
+	return ret;
+}
+
+static int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op)
+{
+	struct pl330_thread *thrd = ch_id;
+	struct pl330_dmac *pl330;
+	unsigned long flags;
+	int ret = 0, active = thrd->req_running;
+
+	if (!thrd || thrd->free || thrd->dmac->state == DYING)
+		return -EINVAL;
+
+	pl330 = thrd->dmac;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+
+	switch (op) {
+	case PL330_OP_FLUSH:
+		/* Make sure the channel is stopped */
+		_stop(thrd);
+
+		thrd->req[0].r = NULL;
+		thrd->req[1].r = NULL;
+		mark_free(thrd, 0);
+		mark_free(thrd, 1);
+		break;
+
+	case PL330_OP_ABORT:
+		/* Make sure the channel is stopped */
+		_stop(thrd);
+
+		/* ABORT is only for the active req */
+		if (active == -1)
+			break;
+
+		thrd->req[active].r = NULL;
+		mark_free(thrd, active);
+
+		/* Start the next */
+	case PL330_OP_START:
+		if ((active == -1) && !_start(thrd))
+			ret = -EIO;
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	spin_unlock_irqrestore(&pl330->lock, flags);
+	return ret;
+}
+
+/* Reserve an event */
+static inline int _alloc_event(struct pl330_thread *thrd)
+{
+	struct pl330_dmac *pl330 = thrd->dmac;
+	struct pl330_info *pi = pl330->pinfo;
+	int ev;
+
+	for (ev = 0; ev < pi->pcfg.num_events; ev++)
+		if (pl330->events[ev] == -1) {
+			pl330->events[ev] = thrd->id;
+			return ev;
+		}
+
+	return -1;
+}
+
+/* Upon success, returns IdentityToken for the
+ * allocated channel, NULL otherwise.
+ */
+static void *pl330_request_channel(const struct pl330_info *pi)
+{
+	struct pl330_thread *thrd = NULL;
+	struct pl330_dmac *pl330;
+	unsigned long flags;
+	int chans, i;
+
+	if (!pi || !pi->pl330_data)
+		return NULL;
+
+	pl330 = pi->pl330_data;
+
+	if (pl330->state == DYING)
+		return NULL;
+
+	chans = pi->pcfg.num_chan;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+
+	for (i = 0; i < chans; i++) {
+		thrd = &pl330->channels[i];
+		if (thrd->free) {
+			thrd->ev = _alloc_event(thrd);
+			if (thrd->ev >= 0) {
+				thrd->free = false;
+				thrd->lstenq = 1;
+				thrd->req[0].r = NULL;
+				mark_free(thrd, 0);
+				thrd->req[1].r = NULL;
+				mark_free(thrd, 1);
+				break;
+			}
+		}
+		thrd = NULL;
+	}
+
+	spin_unlock_irqrestore(&pl330->lock, flags);
+
+	return thrd;
+}
+
+/* Release an event */
+static inline void _free_event(struct pl330_thread *thrd, int ev)
+{
+	struct pl330_dmac *pl330 = thrd->dmac;
+	struct pl330_info *pi = pl330->pinfo;
+
+	/* If the event is valid and was held by the thread */
+	if (ev >= 0 && ev < pi->pcfg.num_events
+			&& pl330->events[ev] == thrd->id)
+		pl330->events[ev] = -1;
+}
+
+static void pl330_release_channel(void *ch_id)
+{
+	struct pl330_thread *thrd = ch_id;
+	struct pl330_dmac *pl330;
+	unsigned long flags;
+
+	if (!thrd || thrd->free)
+		return;
+
+	_stop(thrd);
+
+	_callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT);
+	_callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT);
+
+	pl330 = thrd->dmac;
+
+	spin_lock_irqsave(&pl330->lock, flags);
+	_free_event(thrd, thrd->ev);
+	thrd->free = true;
+	spin_unlock_irqrestore(&pl330->lock, flags);
+}
+
+/* Initialize the structure for PL330 configuration, that can be used
+ * by the client driver the make best use of the DMAC
+ */
+static void read_dmac_config(struct pl330_info *pi)
+{
+	void __iomem *regs = pi->base;
+	u32 val;
+
+	val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
+	val &= CRD_DATA_WIDTH_MASK;
+	pi->pcfg.data_bus_width = 8 * (1 << val);
+
+	val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
+	val &= CRD_DATA_BUFF_MASK;
+	pi->pcfg.data_buf_dep = val + 1;
+
+	val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
+	val &= CR0_NUM_CHANS_MASK;
+	val += 1;
+	pi->pcfg.num_chan = val;
+
+	val = readl(regs + CR0);
+	if (val & CR0_PERIPH_REQ_SET) {
+		val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
+		val += 1;
+		pi->pcfg.num_peri = val;
+		pi->pcfg.peri_ns = readl(regs + CR4);
+	} else {
+		pi->pcfg.num_peri = 0;
+	}
+
+	val = readl(regs + CR0);
+	if (val & CR0_BOOT_MAN_NS)
+		pi->pcfg.mode |= DMAC_MODE_NS;
+	else
+		pi->pcfg.mode &= ~DMAC_MODE_NS;
+
+	val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
+	val &= CR0_NUM_EVENTS_MASK;
+	val += 1;
+	pi->pcfg.num_events = val;
+
+	pi->pcfg.irq_ns = readl(regs + CR3);
+
+	pi->pcfg.periph_id = get_id(pi, PERIPH_ID);
+	pi->pcfg.pcell_id = get_id(pi, PCELL_ID);
+}
+
+static inline void _reset_thread(struct pl330_thread *thrd)
+{
+	struct pl330_dmac *pl330 = thrd->dmac;
+	struct pl330_info *pi = pl330->pinfo;
+
+	thrd->req[0].mc_cpu = pl330->mcode_cpu
+				+ (thrd->id * pi->mcbufsz);
+	thrd->req[0].mc_bus = pl330->mcode_bus
+				+ (thrd->id * pi->mcbufsz);
+	thrd->req[0].r = NULL;
+	mark_free(thrd, 0);
+
+	thrd->req[1].mc_cpu = thrd->req[0].mc_cpu
+				+ pi->mcbufsz / 2;
+	thrd->req[1].mc_bus = thrd->req[0].mc_bus
+				+ pi->mcbufsz / 2;
+	thrd->req[1].r = NULL;
+	mark_free(thrd, 1);
+}
+
+static int dmac_alloc_threads(struct pl330_dmac *pl330)
+{
+	struct pl330_info *pi = pl330->pinfo;
+	int chans = pi->pcfg.num_chan;
+	struct pl330_thread *thrd;
+	int i;
+
+	/* Allocate 1 Manager and 'chans' Channel threads */
+	pl330->channels = kzalloc((1 + chans) * sizeof(*thrd),
+					GFP_KERNEL);
+	if (!pl330->channels)
+		return -ENOMEM;
+
+	/* Init Channel threads */
+	for (i = 0; i < chans; i++) {
+		thrd = &pl330->channels[i];
+		thrd->id = i;
+		thrd->dmac = pl330;
+		_reset_thread(thrd);
+		thrd->free = true;
+	}
+
+	/* MANAGER is indexed at the end */
+	thrd = &pl330->channels[chans];
+	thrd->id = chans;
+	thrd->dmac = pl330;
+	thrd->free = false;
+	pl330->manager = thrd;
+
+	return 0;
+}
+
+static int dmac_alloc_resources(struct pl330_dmac *pl330)
+{
+	struct pl330_info *pi = pl330->pinfo;
+	int chans = pi->pcfg.num_chan;
+	int ret;
+
+	/*
+	 * Alloc MicroCode buffer for 'chans' Channel threads.
+	 * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN)
+	 */
+	pl330->mcode_cpu = dma_alloc_coherent(pi->dev,
+				chans * pi->mcbufsz,
+				&pl330->mcode_bus, GFP_KERNEL);
+	if (!pl330->mcode_cpu) {
+		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	ret = dmac_alloc_threads(pl330);
+	if (ret) {
+		dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n",
+			__func__, __LINE__);
+		dma_free_coherent(pi->dev,
+				chans * pi->mcbufsz,
+				pl330->mcode_cpu, pl330->mcode_bus);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int pl330_add(struct pl330_info *pi)
+{
+	struct pl330_dmac *pl330;
+	void __iomem *regs;
+	int i, ret;
+
+	if (!pi || !pi->dev)
+		return -EINVAL;
+
+	/* If already added */
+	if (pi->pl330_data)
+		return -EINVAL;
+
+	/*
+	 * If the SoC can perform reset on the DMAC, then do it
+	 * before reading its configuration.
+	 */
+	if (pi->dmac_reset)
+		pi->dmac_reset(pi);
+
+	regs = pi->base;
+
+	/* Check if we can handle this DMAC */
+	if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
+	   || get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
+		dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
+			get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
+		return -EINVAL;
+	}
+
+	/* Read the configuration of the DMAC */
+	read_dmac_config(pi);
+
+	if (pi->pcfg.num_events == 0) {
+		dev_err(pi->dev, "%s:%d Can't work without events!\n",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL);
+	if (!pl330) {
+		dev_err(pi->dev, "%s:%d Can't allocate memory!\n",
+			__func__, __LINE__);
+		return -ENOMEM;
+	}
+
+	/* Assign the info structure and private data */
+	pl330->pinfo = pi;
+	pi->pl330_data = pl330;
+
+	spin_lock_init(&pl330->lock);
+
+	INIT_LIST_HEAD(&pl330->req_done);
+
+	/* Use default MC buffer size if not provided */
+	if (!pi->mcbufsz)
+		pi->mcbufsz = MCODE_BUFF_PER_REQ * 2;
+
+	/* Mark all events as free */
+	for (i = 0; i < pi->pcfg.num_events; i++)
+		pl330->events[i] = -1;
+
+	/* Allocate resources needed by the DMAC */
+	ret = dmac_alloc_resources(pl330);
+	if (ret) {
+		dev_err(pi->dev, "Unable to create channels for DMAC\n");
+		kfree(pl330);
+		return ret;
+	}
+
+	tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330);
+
+	pl330->state = INIT;
+
+	return 0;
+}
+
+static int dmac_free_threads(struct pl330_dmac *pl330)
+{
+	struct pl330_info *pi = pl330->pinfo;
+	int chans = pi->pcfg.num_chan;
+	struct pl330_thread *thrd;
+	int i;
+
+	/* Release Channel threads */
+	for (i = 0; i < chans; i++) {
+		thrd = &pl330->channels[i];
+		pl330_release_channel((void *)thrd);
+	}
+
+	/* Free memory */
+	kfree(pl330->channels);
+
+	return 0;
+}
+
+static void dmac_free_resources(struct pl330_dmac *pl330)
+{
+	struct pl330_info *pi = pl330->pinfo;
+	int chans = pi->pcfg.num_chan;
+
+	dmac_free_threads(pl330);
+
+	dma_free_coherent(pi->dev, chans * pi->mcbufsz,
+				pl330->mcode_cpu, pl330->mcode_bus);
+}
+
+static void pl330_del(struct pl330_info *pi)
+{
+	struct pl330_dmac *pl330;
+
+	if (!pi || !pi->pl330_data)
+		return;
+
+	pl330 = pi->pl330_data;
+
+	pl330->state = UNINIT;
+
+	tasklet_kill(&pl330->tasks);
+
+	/* Free DMAC resources */
+	dmac_free_resources(pl330);
+
+	kfree(pl330);
+	pi->pl330_data = NULL;
+}
+
 /* forward declaration */
 static struct amba_driver pl330_driver;
 
@@ -553,6 +2402,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 	async_tx_ack(&desc->txd);
 
 	desc->req.peri = peri_id ? pch->chan.chan_id : 0;
+	desc->rqcfg.pcfg = &pch->dmac->pif.pcfg;
 
 	dma_async_tx_descriptor_init(&desc->txd, &pch->chan);
 
@@ -860,8 +2710,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	INIT_LIST_HEAD(&pd->channels);
 
 	/* Initialize channel parameters */
-	num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri,
-			(u8)pi->pcfg.num_chan);
+	num_chan = max(pdat ? (int)pdat->nr_valid_peri : (int)pi->pcfg.num_peri,
+			(int)pi->pcfg.num_chan);
 	pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
 
 	for (i = 0; i < num_chan; i++) {
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index c9eee6d..6a83d49 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1132,12 +1132,36 @@ static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
 		return ddr2_cs_size(cs_mode, dclr & WIDTH_128);
 	}
 	else if (pvt->ext_model >= K8_REV_D) {
+		unsigned diff;
 		WARN_ON(cs_mode > 10);
 
-		if (cs_mode == 3 || cs_mode == 8)
-			return 32 << (cs_mode - 1);
-		else
-			return 32 << cs_mode;
+		/*
+		 * the below calculation, besides trying to win an obfuscated C
+		 * contest, maps cs_mode values to DIMM chip select sizes. The
+		 * mappings are:
+		 *
+		 * cs_mode	CS size (mb)
+		 * =======	============
+		 * 0		32
+		 * 1		64
+		 * 2		128
+		 * 3		128
+		 * 4		256
+		 * 5		512
+		 * 6		256
+		 * 7		512
+		 * 8		1024
+		 * 9		1024
+		 * 10		2048
+		 *
+		 * Basically, it calculates a value with which to shift the
+		 * smallest CS size of 32MB.
+		 *
+		 * ddr[23]_cs_size have a similar purpose.
+		 */
+		diff = cs_mode/3 + (unsigned)(cs_mode > 5);
+
+		return 32 << (cs_mode - diff);
 	}
 	else {
 		WARN_ON(cs_mode > 6);
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index ca6c04d..da09cd7 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -620,13 +620,13 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset,
 	if (PageHighMem(pg))
 		local_irq_save(flags);
 
-	virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
+	virt_addr = kmap_atomic(pg);
 
 	/* Perform architecture specific atomic scrub operation */
 	atomic_scrub(virt_addr + offset, size);
 
 	/* Unmap and complete */
-	kunmap_atomic(virt_addr, KM_BOUNCE_READ);
+	kunmap_atomic(virt_addr);
 
 	if (PageHighMem(pg))
 		local_irq_restore(flags);
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index d56e634..e9a28f5 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -452,7 +452,7 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
 	int new_bw = 0;
 
 	if (!mci->set_sdram_scrub_rate)
-		return -EINVAL;
+		return -ENODEV;
 
 	if (strict_strtoul(data, 10, &bandwidth) < 0)
 		return -EINVAL;
@@ -475,7 +475,7 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
 	int bandwidth = 0;
 
 	if (!mci->get_sdram_scrub_rate)
-		return -EINVAL;
+		return -ENODEV;
 
 	bandwidth = mci->get_sdram_scrub_rate(mci);
 	if (bandwidth < 0) {
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 5928653..4b8653b 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -41,10 +41,10 @@ drm_clflush_page(struct page *page)
 	if (unlikely(page == NULL))
 		return;
 
-	page_virtual = kmap_atomic(page, KM_USER0);
+	page_virtual = kmap_atomic(page);
 	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
 		clflush(page_virtual + i);
-	kunmap_atomic(page_virtual, KM_USER0);
+	kunmap_atomic(page_virtual);
 }
 
 static void drm_cache_flush_clflush(struct page *pages[],
@@ -87,10 +87,10 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)
 		if (unlikely(page == NULL))
 			continue;
 
-		page_virtual = kmap_atomic(page, KM_USER0);
+		page_virtual = kmap_atomic(page);
 		flush_dcache_range((unsigned long)page_virtual,
 				   (unsigned long)page_virtual + PAGE_SIZE);
-		kunmap_atomic(page_virtual, KM_USER0);
+		kunmap_atomic(page_virtual);
 	}
 #else
 	printk(KERN_ERR "Architecture has no drm_cache.c support\n");
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index 2f75d20..c10cf5e 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -309,11 +309,11 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
 			goto out_err;
 
 		preempt_disable();
-		from_virtual = kmap_atomic(from_page, KM_USER0);
-		to_virtual = kmap_atomic(to_page, KM_USER1);
+		from_virtual = kmap_atomic(from_page);
+		to_virtual = kmap_atomic(to_page);
 		memcpy(to_virtual, from_virtual, PAGE_SIZE);
-		kunmap_atomic(to_virtual, KM_USER1);
-		kunmap_atomic(from_virtual, KM_USER0);
+		kunmap_atomic(to_virtual);
+		kunmap_atomic(from_virtual);
 		preempt_enable();
 		page_cache_release(from_page);
 	}
@@ -365,11 +365,11 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 			goto out_err;
 		}
 		preempt_disable();
-		from_virtual = kmap_atomic(from_page, KM_USER0);
-		to_virtual = kmap_atomic(to_page, KM_USER1);
+		from_virtual = kmap_atomic(from_page);
+		to_virtual = kmap_atomic(to_page);
 		memcpy(to_virtual, from_virtual, PAGE_SIZE);
-		kunmap_atomic(to_virtual, KM_USER1);
-		kunmap_atomic(from_virtual, KM_USER0);
+		kunmap_atomic(to_virtual);
+		kunmap_atomic(from_virtual);
 		preempt_enable();
 		set_page_dirty(to_page);
 		mark_page_accessed(to_page);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
index f4e7763..51c9ba5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c
@@ -136,10 +136,10 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages,
 
 		if (likely(page_virtual != NULL)) {
 			desc_virtual->ppn = page_to_pfn(page);
-			kunmap_atomic(page_virtual, KM_USER0);
+			kunmap_atomic(page_virtual);
 		}
 
-		page_virtual = kmap_atomic(page, KM_USER0);
+		page_virtual = kmap_atomic(page);
 		desc_virtual = page_virtual - 1;
 		prev_pfn = ~(0UL);
 
@@ -169,7 +169,7 @@ static int vmw_gmr_build_descriptors(struct list_head *desc_pages,
 	}
 
 	if (likely(page_virtual != NULL))
-		kunmap_atomic(page_virtual, KM_USER0);
+		kunmap_atomic(page_virtual);
 
 	return 0;
 out_err:
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
new file mode 100644
index 0000000..d94e38d
--- /dev/null
+++ b/drivers/hsi/Kconfig
@@ -0,0 +1,19 @@
+#
+# HSI driver configuration
+#
+menuconfig HSI
+	tristate "HSI support"
+	---help---
+	  The "High speed synchronous Serial Interface" is
+	  synchronous serial interface used mainly to connect
+	  application engines and cellular modems.
+
+if HSI
+
+config HSI_BOARDINFO
+	bool
+	default y
+
+source "drivers/hsi/clients/Kconfig"
+
+endif # HSI
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
new file mode 100644
index 0000000..9d5d33f
--- /dev/null
+++ b/drivers/hsi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for HSI
+#
+obj-$(CONFIG_HSI_BOARDINFO)	+= hsi_boardinfo.o
+obj-$(CONFIG_HSI)		+= hsi.o
+obj-y				+= clients/
diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig
new file mode 100644
index 0000000..3bacd27
--- /dev/null
+++ b/drivers/hsi/clients/Kconfig
@@ -0,0 +1,13 @@
+#
+# HSI clients configuration
+#
+
+comment "HSI clients"
+
+config HSI_CHAR
+	tristate "HSI/SSI character driver"
+	depends on HSI
+	---help---
+	  If you say Y here, you will enable the HSI/SSI character driver.
+	  This driver provides a simple character device interface for
+	  serial communication with the cellular modem over HSI/SSI bus.
diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile
new file mode 100644
index 0000000..327c0e2
--- /dev/null
+++ b/drivers/hsi/clients/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for HSI clients
+#
+
+obj-$(CONFIG_HSI_CHAR)	+= hsi_char.o
diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c
new file mode 100644
index 0000000..88a050d
--- /dev/null
+++ b/drivers/hsi/clients/hsi_char.c
@@ -0,0 +1,802 @@
+/*
+ * HSI character device driver, implements the character device
+ * interface.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <linux/stat.h>
+#include <linux/hsi/hsi.h>
+#include <linux/hsi/hsi_char.h>
+
+#define HSC_DEVS		16 /* Num of channels */
+#define HSC_MSGS		4
+
+#define HSC_RXBREAK		0
+
+#define HSC_ID_BITS		6
+#define HSC_PORT_ID_BITS	4
+#define HSC_ID_MASK		3
+#define HSC_PORT_ID_MASK	3
+#define HSC_CH_MASK		0xf
+
+/*
+ * We support up to 4 controllers that can have up to 4
+ * ports, which should currently be more than enough.
+ */
+#define HSC_BASEMINOR(id, port_id) \
+		((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \
+		(((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS))
+
+enum {
+	HSC_CH_OPEN,
+	HSC_CH_READ,
+	HSC_CH_WRITE,
+	HSC_CH_WLINE,
+};
+
+enum {
+	HSC_RX,
+	HSC_TX,
+};
+
+struct hsc_client_data;
+/**
+ * struct hsc_channel - hsi_char internal channel data
+ * @ch: channel number
+ * @flags: Keeps state of the channel (open/close, reading, writing)
+ * @free_msgs_list: List of free HSI messages/requests
+ * @rx_msgs_queue: List of pending RX requests
+ * @tx_msgs_queue: List of pending TX requests
+ * @lock: Serialize access to the lists
+ * @cl: reference to the associated hsi_client
+ * @cl_data: reference to the client data that this channels belongs to
+ * @rx_wait: RX requests wait queue
+ * @tx_wait: TX requests wait queue
+ */
+struct hsc_channel {
+	unsigned int		ch;
+	unsigned long		flags;
+	struct list_head	free_msgs_list;
+	struct list_head	rx_msgs_queue;
+	struct list_head	tx_msgs_queue;
+	spinlock_t		lock;
+	struct hsi_client	*cl;
+	struct hsc_client_data *cl_data;
+	wait_queue_head_t	rx_wait;
+	wait_queue_head_t	tx_wait;
+};
+
+/**
+ * struct hsc_client_data - hsi_char internal client data
+ * @cdev: Characther device associated to the hsi_client
+ * @lock: Lock to serialize open/close access
+ * @flags: Keeps track of port state (rx hwbreak armed)
+ * @usecnt: Use count for claiming the HSI port (mutex protected)
+ * @cl: Referece to the HSI client
+ * @channels: Array of channels accessible by the client
+ */
+struct hsc_client_data {
+	struct cdev		cdev;
+	struct mutex		lock;
+	unsigned long		flags;
+	unsigned int		usecnt;
+	struct hsi_client	*cl;
+	struct hsc_channel	channels[HSC_DEVS];
+};
+
+/* Stores the major number dynamically allocated for hsi_char */
+static unsigned int hsc_major;
+/* Maximum buffer size that hsi_char will accept from userspace */
+static unsigned int max_data_size = 0x1000;
+module_param(max_data_size, uint, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
+
+static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
+							struct list_head *queue)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->lock, flags);
+	list_add_tail(&msg->link, queue);
+	spin_unlock_irqrestore(&channel->lock, flags);
+}
+
+static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel,
+							struct list_head *queue)
+{
+	struct hsi_msg *msg = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->lock, flags);
+
+	if (list_empty(queue))
+		goto out;
+
+	msg = list_first_entry(queue, struct hsi_msg, link);
+	list_del(&msg->link);
+out:
+	spin_unlock_irqrestore(&channel->lock, flags);
+
+	return msg;
+}
+
+static inline void hsc_msg_free(struct hsi_msg *msg)
+{
+	kfree(sg_virt(msg->sgt.sgl));
+	hsi_free_msg(msg);
+}
+
+static void hsc_free_list(struct list_head *list)
+{
+	struct hsi_msg *msg, *tmp;
+
+	list_for_each_entry_safe(msg, tmp, list, link) {
+		list_del(&msg->link);
+		hsc_msg_free(msg);
+	}
+}
+
+static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l)
+{
+	unsigned long flags;
+	LIST_HEAD(list);
+
+	spin_lock_irqsave(&channel->lock, flags);
+	list_splice_init(l, &list);
+	spin_unlock_irqrestore(&channel->lock, flags);
+
+	hsc_free_list(&list);
+}
+
+static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)
+{
+	struct hsi_msg *msg;
+	void *buf;
+
+	msg = hsi_alloc_msg(1, GFP_KERNEL);
+	if (!msg)
+		goto out;
+	buf = kmalloc(alloc_size, GFP_KERNEL);
+	if (!buf) {
+		hsi_free_msg(msg);
+		goto out;
+	}
+	sg_init_one(msg->sgt.sgl, buf, alloc_size);
+	/* Ignore false positive, due to sg pointer handling */
+	kmemleak_ignore(buf);
+
+	return msg;
+out:
+	return NULL;
+}
+
+static inline int hsc_msgs_alloc(struct hsc_channel *channel)
+{
+	struct hsi_msg *msg;
+	int i;
+
+	for (i = 0; i < HSC_MSGS; i++) {
+		msg = hsc_msg_alloc(max_data_size);
+		if (!msg)
+			goto out;
+		msg->channel = channel->ch;
+		list_add_tail(&msg->link, &channel->free_msgs_list);
+	}
+
+	return 0;
+out:
+	hsc_free_list(&channel->free_msgs_list);
+
+	return -ENOMEM;
+}
+
+static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg)
+{
+	return msg->sgt.sgl->length;
+}
+
+static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len)
+{
+	msg->sgt.sgl->length = len;
+}
+
+static void hsc_rx_completed(struct hsi_msg *msg)
+{
+	struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+	struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+	if (test_bit(HSC_CH_READ, &channel->flags)) {
+		hsc_add_tail(channel, msg, &channel->rx_msgs_queue);
+		wake_up(&channel->rx_wait);
+	} else {
+		hsc_add_tail(channel, msg, &channel->free_msgs_list);
+	}
+}
+
+static void hsc_rx_msg_destructor(struct hsi_msg *msg)
+{
+	msg->status = HSI_STATUS_ERROR;
+	hsc_msg_len_set(msg, 0);
+	hsc_rx_completed(msg);
+}
+
+static void hsc_tx_completed(struct hsi_msg *msg)
+{
+	struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+	struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+	if (test_bit(HSC_CH_WRITE, &channel->flags)) {
+		hsc_add_tail(channel, msg, &channel->tx_msgs_queue);
+		wake_up(&channel->tx_wait);
+	} else {
+		hsc_add_tail(channel, msg, &channel->free_msgs_list);
+	}
+}
+
+static void hsc_tx_msg_destructor(struct hsi_msg *msg)
+{
+	msg->status = HSI_STATUS_ERROR;
+	hsc_msg_len_set(msg, 0);
+	hsc_tx_completed(msg);
+}
+
+static void hsc_break_req_destructor(struct hsi_msg *msg)
+{
+	struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+
+	hsi_free_msg(msg);
+	clear_bit(HSC_RXBREAK, &cl_data->flags);
+}
+
+static void hsc_break_received(struct hsi_msg *msg)
+{
+	struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+	struct hsc_channel *channel = cl_data->channels;
+	int i, ret;
+
+	/* Broadcast HWBREAK on all channels */
+	for (i = 0; i < HSC_DEVS; i++, channel++) {
+		struct hsi_msg *msg2;
+
+		if (!test_bit(HSC_CH_READ, &channel->flags))
+			continue;
+		msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list);
+		if (!msg2)
+			continue;
+		clear_bit(HSC_CH_READ, &channel->flags);
+		hsc_msg_len_set(msg2, 0);
+		msg2->status = HSI_STATUS_COMPLETED;
+		hsc_add_tail(channel, msg2, &channel->rx_msgs_queue);
+		wake_up(&channel->rx_wait);
+	}
+	hsi_flush(msg->cl);
+	ret = hsi_async_read(msg->cl, msg);
+	if (ret < 0)
+		hsc_break_req_destructor(msg);
+}
+
+static int hsc_break_request(struct hsi_client *cl)
+{
+	struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+	struct hsi_msg *msg;
+	int ret;
+
+	if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags))
+		return -EBUSY;
+
+	msg = hsi_alloc_msg(0, GFP_KERNEL);
+	if (!msg) {
+		clear_bit(HSC_RXBREAK, &cl_data->flags);
+		return -ENOMEM;
+	}
+	msg->break_frame = 1;
+	msg->complete = hsc_break_received;
+	msg->destructor = hsc_break_req_destructor;
+	ret = hsi_async_read(cl, msg);
+	if (ret < 0)
+		hsc_break_req_destructor(msg);
+
+	return ret;
+}
+
+static int hsc_break_send(struct hsi_client *cl)
+{
+	struct hsi_msg *msg;
+	int ret;
+
+	msg = hsi_alloc_msg(0, GFP_ATOMIC);
+	if (!msg)
+		return -ENOMEM;
+	msg->break_frame = 1;
+	msg->complete = hsi_free_msg;
+	msg->destructor = hsi_free_msg;
+	ret = hsi_async_write(cl, msg);
+	if (ret < 0)
+		hsi_free_msg(msg);
+
+	return ret;
+}
+
+static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+	struct hsi_config tmp;
+	int ret;
+
+	if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME))
+		return -EINVAL;
+	if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS))
+		return -EINVAL;
+	if (rxc->channels & (rxc->channels - 1))
+		return -EINVAL;
+	if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE))
+		return -EINVAL;
+	tmp = cl->rx_cfg;
+	cl->rx_cfg.mode = rxc->mode;
+	cl->rx_cfg.channels = rxc->channels;
+	cl->rx_cfg.flow = rxc->flow;
+	ret = hsi_setup(cl);
+	if (ret < 0) {
+		cl->rx_cfg = tmp;
+		return ret;
+	}
+	if (rxc->mode == HSI_MODE_FRAME)
+		hsc_break_request(cl);
+
+	return ret;
+}
+
+static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+	rxc->mode = cl->rx_cfg.mode;
+	rxc->channels = cl->rx_cfg.channels;
+	rxc->flow = cl->rx_cfg.flow;
+}
+
+static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+	struct hsi_config tmp;
+	int ret;
+
+	if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME))
+		return -EINVAL;
+	if ((txc->channels == 0) || (txc->channels > HSC_DEVS))
+		return -EINVAL;
+	if (txc->channels & (txc->channels - 1))
+		return -EINVAL;
+	if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO))
+		return -EINVAL;
+	tmp = cl->tx_cfg;
+	cl->tx_cfg.mode = txc->mode;
+	cl->tx_cfg.channels = txc->channels;
+	cl->tx_cfg.speed = txc->speed;
+	cl->tx_cfg.arb_mode = txc->arb_mode;
+	ret = hsi_setup(cl);
+	if (ret < 0) {
+		cl->tx_cfg = tmp;
+		return ret;
+	}
+
+	return ret;
+}
+
+static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+	txc->mode = cl->tx_cfg.mode;
+	txc->channels = cl->tx_cfg.channels;
+	txc->speed = cl->tx_cfg.speed;
+	txc->arb_mode = cl->tx_cfg.arb_mode;
+}
+
+static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
+						loff_t *ppos __maybe_unused)
+{
+	struct hsc_channel *channel = file->private_data;
+	struct hsi_msg *msg;
+	ssize_t ret;
+
+	if (len == 0)
+		return 0;
+	if (!IS_ALIGNED(len, sizeof(u32)))
+		return -EINVAL;
+	if (len > max_data_size)
+		len = max_data_size;
+	if (channel->ch >= channel->cl->rx_cfg.channels)
+		return -ECHRNG;
+	if (test_and_set_bit(HSC_CH_READ, &channel->flags))
+		return -EBUSY;
+	msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+	if (!msg) {
+		ret = -ENOSPC;
+		goto out;
+	}
+	hsc_msg_len_set(msg, len);
+	msg->complete = hsc_rx_completed;
+	msg->destructor = hsc_rx_msg_destructor;
+	ret = hsi_async_read(channel->cl, msg);
+	if (ret < 0) {
+		hsc_add_tail(channel, msg, &channel->free_msgs_list);
+		goto out;
+	}
+
+	ret = wait_event_interruptible(channel->rx_wait,
+					!list_empty(&channel->rx_msgs_queue));
+	if (ret < 0) {
+		clear_bit(HSC_CH_READ, &channel->flags);
+		hsi_flush(channel->cl);
+		return -EINTR;
+	}
+
+	msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
+	if (msg) {
+		if (msg->status != HSI_STATUS_ERROR) {
+			ret = copy_to_user((void __user *)buf,
+			sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
+			if (ret)
+				ret = -EFAULT;
+			else
+				ret = hsc_msg_len_get(msg);
+		} else {
+			ret = -EIO;
+		}
+		hsc_add_tail(channel, msg, &channel->free_msgs_list);
+	}
+out:
+	clear_bit(HSC_CH_READ, &channel->flags);
+
+	return ret;
+}
+
+static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
+						loff_t *ppos __maybe_unused)
+{
+	struct hsc_channel *channel = file->private_data;
+	struct hsi_msg *msg;
+	ssize_t ret;
+
+	if ((len == 0) || !IS_ALIGNED(len, sizeof(u32)))
+		return -EINVAL;
+	if (len > max_data_size)
+		len = max_data_size;
+	if (channel->ch >= channel->cl->tx_cfg.channels)
+		return -ECHRNG;
+	if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
+		return -EBUSY;
+	msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+	if (!msg) {
+		clear_bit(HSC_CH_WRITE, &channel->flags);
+		return -ENOSPC;
+	}
+	if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	hsc_msg_len_set(msg, len);
+	msg->complete = hsc_tx_completed;
+	msg->destructor = hsc_tx_msg_destructor;
+	ret = hsi_async_write(channel->cl, msg);
+	if (ret < 0)
+		goto out;
+
+	ret = wait_event_interruptible(channel->tx_wait,
+					!list_empty(&channel->tx_msgs_queue));
+	if (ret < 0) {
+		clear_bit(HSC_CH_WRITE, &channel->flags);
+		hsi_flush(channel->cl);
+		return -EINTR;
+	}
+
+	msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue);
+	if (msg) {
+		if (msg->status == HSI_STATUS_ERROR)
+			ret = -EIO;
+		else
+			ret = hsc_msg_len_get(msg);
+
+		hsc_add_tail(channel, msg, &channel->free_msgs_list);
+	}
+out:
+	clear_bit(HSC_CH_WRITE, &channel->flags);
+
+	return ret;
+}
+
+static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct hsc_channel *channel = file->private_data;
+	unsigned int state;
+	struct hsc_rx_config rxc;
+	struct hsc_tx_config txc;
+	long ret = 0;
+
+	switch (cmd) {
+	case HSC_RESET:
+		hsi_flush(channel->cl);
+		break;
+	case HSC_SET_PM:
+		if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
+			return -EFAULT;
+		if (state == HSC_PM_DISABLE) {
+			if (test_and_set_bit(HSC_CH_WLINE, &channel->flags))
+				return -EINVAL;
+			ret = hsi_start_tx(channel->cl);
+		} else if (state == HSC_PM_ENABLE) {
+			if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+				return -EINVAL;
+			ret = hsi_stop_tx(channel->cl);
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	case HSC_SEND_BREAK:
+		return hsc_break_send(channel->cl);
+	case HSC_SET_RX:
+		if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc)))
+			return -EFAULT;
+		return hsc_rx_set(channel->cl, &rxc);
+	case HSC_GET_RX:
+		hsc_rx_get(channel->cl, &rxc);
+		if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc)))
+			return -EFAULT;
+		break;
+	case HSC_SET_TX:
+		if (copy_from_user(&txc, (void __user *)arg, sizeof(txc)))
+			return -EFAULT;
+		return hsc_tx_set(channel->cl, &txc);
+	case HSC_GET_TX:
+		hsc_tx_get(channel->cl, &txc);
+		if (copy_to_user((void __user *)arg, &txc, sizeof(txc)))
+			return -EFAULT;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+
+static inline void __hsc_port_release(struct hsc_client_data *cl_data)
+{
+	BUG_ON(cl_data->usecnt == 0);
+
+	if (--cl_data->usecnt == 0) {
+		hsi_flush(cl_data->cl);
+		hsi_release_port(cl_data->cl);
+	}
+}
+
+static int hsc_open(struct inode *inode, struct file *file)
+{
+	struct hsc_client_data *cl_data;
+	struct hsc_channel *channel;
+	int ret = 0;
+
+	pr_debug("open, minor = %d\n", iminor(inode));
+
+	cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev);
+	mutex_lock(&cl_data->lock);
+	channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK);
+
+	if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	/*
+	 * Check if we have already claimed the port associated to the HSI
+	 * client. If not then try to claim it, else increase its refcount
+	 */
+	if (cl_data->usecnt == 0) {
+		ret = hsi_claim_port(cl_data->cl, 0);
+		if (ret < 0)
+			goto out;
+		hsi_setup(cl_data->cl);
+	}
+	cl_data->usecnt++;
+
+	ret = hsc_msgs_alloc(channel);
+	if (ret < 0) {
+		__hsc_port_release(cl_data);
+		goto out;
+	}
+
+	file->private_data = channel;
+	mutex_unlock(&cl_data->lock);
+
+	return ret;
+out:
+	mutex_unlock(&cl_data->lock);
+
+	return ret;
+}
+
+static int hsc_release(struct inode *inode __maybe_unused, struct file *file)
+{
+	struct hsc_channel *channel = file->private_data;
+	struct hsc_client_data *cl_data = channel->cl_data;
+
+	mutex_lock(&cl_data->lock);
+	file->private_data = NULL;
+	if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+		hsi_stop_tx(channel->cl);
+	__hsc_port_release(cl_data);
+	hsc_reset_list(channel, &channel->rx_msgs_queue);
+	hsc_reset_list(channel, &channel->tx_msgs_queue);
+	hsc_reset_list(channel, &channel->free_msgs_list);
+	clear_bit(HSC_CH_READ, &channel->flags);
+	clear_bit(HSC_CH_WRITE, &channel->flags);
+	clear_bit(HSC_CH_OPEN, &channel->flags);
+	wake_up(&channel->rx_wait);
+	wake_up(&channel->tx_wait);
+	mutex_unlock(&cl_data->lock);
+
+	return 0;
+}
+
+static const struct file_operations hsc_fops = {
+	.owner		= THIS_MODULE,
+	.read		= hsc_read,
+	.write		= hsc_write,
+	.unlocked_ioctl	= hsc_ioctl,
+	.open		= hsc_open,
+	.release	= hsc_release,
+};
+
+static void __devinit hsc_channel_init(struct hsc_channel *channel)
+{
+	init_waitqueue_head(&channel->rx_wait);
+	init_waitqueue_head(&channel->tx_wait);
+	spin_lock_init(&channel->lock);
+	INIT_LIST_HEAD(&channel->free_msgs_list);
+	INIT_LIST_HEAD(&channel->rx_msgs_queue);
+	INIT_LIST_HEAD(&channel->tx_msgs_queue);
+}
+
+static int __devinit hsc_probe(struct device *dev)
+{
+	const char devname[] = "hsi_char";
+	struct hsc_client_data *cl_data;
+	struct hsc_channel *channel;
+	struct hsi_client *cl = to_hsi_client(dev);
+	unsigned int hsc_baseminor;
+	dev_t hsc_dev;
+	int ret;
+	int i;
+
+	cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
+	if (!cl_data) {
+		dev_err(dev, "Could not allocate hsc_client_data\n");
+		return -ENOMEM;
+	}
+	hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
+	if (!hsc_major) {
+		ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
+						HSC_DEVS, devname);
+		if (ret > 0)
+			hsc_major = MAJOR(hsc_dev);
+	} else {
+		hsc_dev = MKDEV(hsc_major, hsc_baseminor);
+		ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
+	}
+	if (ret < 0) {
+		dev_err(dev, "Device %s allocation failed %d\n",
+					hsc_major ? "minor" : "major", ret);
+		goto out1;
+	}
+	mutex_init(&cl_data->lock);
+	hsi_client_set_drvdata(cl, cl_data);
+	cdev_init(&cl_data->cdev, &hsc_fops);
+	cl_data->cdev.owner = THIS_MODULE;
+	cl_data->cl = cl;
+	for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
+		hsc_channel_init(channel);
+		channel->ch = i;
+		channel->cl = cl;
+		channel->cl_data = cl_data;
+	}
+
+	/* 1 hsi client -> N char devices (one for each channel) */
+	ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
+	if (ret) {
+		dev_err(dev, "Could not add char device %d\n", ret);
+		goto out2;
+	}
+
+	return 0;
+out2:
+	unregister_chrdev_region(hsc_dev, HSC_DEVS);
+out1:
+	kfree(cl_data);
+
+	return ret;
+}
+
+static int __devexit hsc_remove(struct device *dev)
+{
+	struct hsi_client *cl = to_hsi_client(dev);
+	struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+	dev_t hsc_dev = cl_data->cdev.dev;
+
+	cdev_del(&cl_data->cdev);
+	unregister_chrdev_region(hsc_dev, HSC_DEVS);
+	hsi_client_set_drvdata(cl, NULL);
+	kfree(cl_data);
+
+	return 0;
+}
+
+static struct hsi_client_driver hsc_driver = {
+	.driver = {
+		.name	= "hsi_char",
+		.owner	= THIS_MODULE,
+		.probe	= hsc_probe,
+		.remove	= __devexit_p(hsc_remove),
+	},
+};
+
+static int __init hsc_init(void)
+{
+	int ret;
+
+	if ((max_data_size < 4) || (max_data_size > 0x10000) ||
+		(max_data_size & (max_data_size - 1))) {
+		pr_err("Invalid max read/write data size");
+		return -EINVAL;
+	}
+
+	ret = hsi_register_client_driver(&hsc_driver);
+	if (ret) {
+		pr_err("Error while registering HSI/SSI driver %d", ret);
+		return ret;
+	}
+
+	pr_info("HSI/SSI char device loaded\n");
+
+	return 0;
+}
+module_init(hsc_init);
+
+static void __exit hsc_exit(void)
+{
+	hsi_unregister_client_driver(&hsc_driver);
+	pr_info("HSI char device removed\n");
+}
+module_exit(hsc_exit);
+
+MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
+MODULE_ALIAS("hsi:hsi_char");
+MODULE_DESCRIPTION("HSI character device");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
new file mode 100644
index 0000000..4e2d79b
--- /dev/null
+++ b/drivers/hsi/hsi.c
@@ -0,0 +1,494 @@
+/*
+ * HSI core.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/compiler.h>
+#include <linux/rwsem.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/kobject.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "hsi_core.h"
+
+static struct device_type hsi_ctrl = {
+	.name	= "hsi_controller",
+};
+
+static struct device_type hsi_cl = {
+	.name	= "hsi_client",
+};
+
+static struct device_type hsi_port = {
+	.name	= "hsi_port",
+};
+
+static ssize_t modalias_show(struct device *dev,
+			struct device_attribute *a __maybe_unused, char *buf)
+{
+	return sprintf(buf, "hsi:%s\n", dev_name(dev));
+}
+
+static struct device_attribute hsi_bus_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
+static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	if (dev->type == &hsi_cl)
+		add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
+
+	return 0;
+}
+
+static int hsi_bus_match(struct device *dev, struct device_driver *driver)
+{
+	return strcmp(dev_name(dev), driver->name) == 0;
+}
+
+static struct bus_type hsi_bus_type = {
+	.name		= "hsi",
+	.dev_attrs	= hsi_bus_dev_attrs,
+	.match		= hsi_bus_match,
+	.uevent		= hsi_bus_uevent,
+};
+
+static void hsi_client_release(struct device *dev)
+{
+	kfree(to_hsi_client(dev));
+}
+
+static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
+{
+	struct hsi_client *cl;
+	unsigned long flags;
+
+	cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+	if (!cl)
+		return;
+	cl->device.type = &hsi_cl;
+	cl->tx_cfg = info->tx_cfg;
+	cl->rx_cfg = info->rx_cfg;
+	cl->device.bus = &hsi_bus_type;
+	cl->device.parent = &port->device;
+	cl->device.release = hsi_client_release;
+	dev_set_name(&cl->device, info->name);
+	cl->device.platform_data = info->platform_data;
+	spin_lock_irqsave(&port->clock, flags);
+	list_add_tail(&cl->link, &port->clients);
+	spin_unlock_irqrestore(&port->clock, flags);
+	if (info->archdata)
+		cl->device.archdata = *info->archdata;
+	if (device_register(&cl->device) < 0) {
+		pr_err("hsi: failed to register client: %s\n", info->name);
+		kfree(cl);
+	}
+}
+
+static void hsi_scan_board_info(struct hsi_controller *hsi)
+{
+	struct hsi_cl_info *cl_info;
+	struct hsi_port	*p;
+
+	list_for_each_entry(cl_info, &hsi_board_list, list)
+		if (cl_info->info.hsi_id == hsi->id) {
+			p = hsi_find_port_num(hsi, cl_info->info.port);
+			if (!p)
+				continue;
+			hsi_new_client(p, &cl_info->info);
+		}
+}
+
+static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
+{
+	struct hsi_client *cl = to_hsi_client(dev);
+	struct hsi_port *port = to_hsi_port(dev->parent);
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->clock, flags);
+	list_del(&cl->link);
+	spin_unlock_irqrestore(&port->clock, flags);
+	device_unregister(dev);
+
+	return 0;
+}
+
+static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
+{
+	device_for_each_child(dev, NULL, hsi_remove_client);
+	device_unregister(dev);
+
+	return 0;
+}
+
+static void hsi_controller_release(struct device *dev __maybe_unused)
+{
+}
+
+static void hsi_port_release(struct device *dev __maybe_unused)
+{
+}
+
+/**
+ * hsi_unregister_controller - Unregister an HSI controller
+ * @hsi: The HSI controller to register
+ */
+void hsi_unregister_controller(struct hsi_controller *hsi)
+{
+	device_for_each_child(&hsi->device, NULL, hsi_remove_port);
+	device_unregister(&hsi->device);
+}
+EXPORT_SYMBOL_GPL(hsi_unregister_controller);
+
+/**
+ * hsi_register_controller - Register an HSI controller and its ports
+ * @hsi: The HSI controller to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_controller(struct hsi_controller *hsi)
+{
+	unsigned int i;
+	int err;
+
+	hsi->device.type = &hsi_ctrl;
+	hsi->device.bus = &hsi_bus_type;
+	hsi->device.release = hsi_controller_release;
+	err = device_register(&hsi->device);
+	if (err < 0)
+		return err;
+	for (i = 0; i < hsi->num_ports; i++) {
+		hsi->port[i].device.parent = &hsi->device;
+		hsi->port[i].device.bus = &hsi_bus_type;
+		hsi->port[i].device.release = hsi_port_release;
+		hsi->port[i].device.type = &hsi_port;
+		INIT_LIST_HEAD(&hsi->port[i].clients);
+		spin_lock_init(&hsi->port[i].clock);
+		err = device_register(&hsi->port[i].device);
+		if (err < 0)
+			goto out;
+	}
+	/* Populate HSI bus with HSI clients */
+	hsi_scan_board_info(hsi);
+
+	return 0;
+out:
+	hsi_unregister_controller(hsi);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(hsi_register_controller);
+
+/**
+ * hsi_register_client_driver - Register an HSI client to the HSI bus
+ * @drv: HSI client driver to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_client_driver(struct hsi_client_driver *drv)
+{
+	drv->driver.bus = &hsi_bus_type;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(hsi_register_client_driver);
+
+static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
+{
+	return 0;
+}
+
+static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
+{
+	return 0;
+}
+
+/**
+ * hsi_alloc_controller - Allocate an HSI controller and its ports
+ * @n_ports: Number of ports on the HSI controller
+ * @flags: Kernel allocation flags
+ *
+ * Return NULL on failure or a pointer to an hsi_controller on success.
+ */
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
+{
+	struct hsi_controller	*hsi;
+	struct hsi_port		*port;
+	unsigned int		i;
+
+	if (!n_ports)
+		return NULL;
+
+	port = kzalloc(sizeof(*port)*n_ports, flags);
+	if (!port)
+		return NULL;
+	hsi = kzalloc(sizeof(*hsi), flags);
+	if (!hsi)
+		goto out;
+	for (i = 0; i < n_ports; i++) {
+		dev_set_name(&port[i].device, "port%d", i);
+		port[i].num = i;
+		port[i].async = hsi_dummy_msg;
+		port[i].setup = hsi_dummy_cl;
+		port[i].flush = hsi_dummy_cl;
+		port[i].start_tx = hsi_dummy_cl;
+		port[i].stop_tx = hsi_dummy_cl;
+		port[i].release = hsi_dummy_cl;
+		mutex_init(&port[i].lock);
+	}
+	hsi->num_ports = n_ports;
+	hsi->port = port;
+
+	return hsi;
+out:
+	kfree(port);
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_controller);
+
+/**
+ * hsi_free_controller - Free an HSI controller
+ * @hsi: Pointer to HSI controller
+ */
+void hsi_free_controller(struct hsi_controller *hsi)
+{
+	if (!hsi)
+		return;
+
+	kfree(hsi->port);
+	kfree(hsi);
+}
+EXPORT_SYMBOL_GPL(hsi_free_controller);
+
+/**
+ * hsi_free_msg - Free an HSI message
+ * @msg: Pointer to the HSI message
+ *
+ * Client is responsible to free the buffers pointed by the scatterlists.
+ */
+void hsi_free_msg(struct hsi_msg *msg)
+{
+	if (!msg)
+		return;
+	sg_free_table(&msg->sgt);
+	kfree(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_free_msg);
+
+/**
+ * hsi_alloc_msg - Allocate an HSI message
+ * @nents: Number of memory entries
+ * @flags: Kernel allocation flags
+ *
+ * nents can be 0. This mainly makes sense for read transfer.
+ * In that case, HSI drivers will call the complete callback when
+ * there is data to be read without consuming it.
+ *
+ * Return NULL on failure or a pointer to an hsi_msg on success.
+ */
+struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
+{
+	struct hsi_msg *msg;
+	int err;
+
+	msg = kzalloc(sizeof(*msg), flags);
+	if (!msg)
+		return NULL;
+
+	if (!nents)
+		return msg;
+
+	err = sg_alloc_table(&msg->sgt, nents, flags);
+	if (unlikely(err)) {
+		kfree(msg);
+		msg = NULL;
+	}
+
+	return msg;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_msg);
+
+/**
+ * hsi_async - Submit an HSI transfer to the controller
+ * @cl: HSI client sending the transfer
+ * @msg: The HSI transfer passed to controller
+ *
+ * The HSI message must have the channel, ttype, complete and destructor
+ * fields set beforehand. If nents > 0 then the client has to initialize
+ * also the scatterlists to point to the buffers to write to or read from.
+ *
+ * HSI controllers relay on pre-allocated buffers from their clients and they
+ * do not allocate buffers on their own.
+ *
+ * Once the HSI message transfer finishes, the HSI controller calls the
+ * complete callback with the status and actual_len fields of the HSI message
+ * updated. The complete callback can be called before returning from
+ * hsi_async.
+ *
+ * Returns -errno on failure or 0 on success
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
+{
+	struct hsi_port *port = hsi_get_port(cl);
+
+	if (!hsi_port_claimed(cl))
+		return -EACCES;
+
+	WARN_ON_ONCE(!msg->destructor || !msg->complete);
+	msg->cl = cl;
+
+	return port->async(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_async);
+
+/**
+ * hsi_claim_port - Claim the HSI client's port
+ * @cl: HSI client that wants to claim its port
+ * @share: Flag to indicate if the client wants to share the port or not.
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_claim_port(struct hsi_client *cl, unsigned int share)
+{
+	struct hsi_port *port = hsi_get_port(cl);
+	int err = 0;
+
+	mutex_lock(&port->lock);
+	if ((port->claimed) && (!port->shared || !share)) {
+		err = -EBUSY;
+		goto out;
+	}
+	if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
+		err = -ENODEV;
+		goto out;
+	}
+	port->claimed++;
+	port->shared = !!share;
+	cl->pclaimed = 1;
+out:
+	mutex_unlock(&port->lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(hsi_claim_port);
+
+/**
+ * hsi_release_port - Release the HSI client's port
+ * @cl: HSI client which previously claimed its port
+ */
+void hsi_release_port(struct hsi_client *cl)
+{
+	struct hsi_port *port = hsi_get_port(cl);
+
+	mutex_lock(&port->lock);
+	/* Allow HW driver to do some cleanup */
+	port->release(cl);
+	if (cl->pclaimed)
+		port->claimed--;
+	BUG_ON(port->claimed < 0);
+	cl->pclaimed = 0;
+	if (!port->claimed)
+		port->shared = 0;
+	module_put(to_hsi_controller(port->device.parent)->owner);
+	mutex_unlock(&port->lock);
+}
+EXPORT_SYMBOL_GPL(hsi_release_port);
+
+static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused)
+{
+	if (cl->hsi_start_rx)
+		(*cl->hsi_start_rx)(cl);
+
+	return 0;
+}
+
+static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused)
+{
+	if (cl->hsi_stop_rx)
+		(*cl->hsi_stop_rx)(cl);
+
+	return 0;
+}
+
+static int hsi_port_for_each_client(struct hsi_port *port, void *data,
+				int (*fn)(struct hsi_client *cl, void *data))
+{
+	struct hsi_client *cl;
+
+	spin_lock(&port->clock);
+	list_for_each_entry(cl, &port->clients, link) {
+		spin_unlock(&port->clock);
+		(*fn)(cl, data);
+		spin_lock(&port->clock);
+	}
+	spin_unlock(&port->clock);
+
+	return 0;
+}
+
+/**
+ * hsi_event -Notifies clients about port events
+ * @port: Port where the event occurred
+ * @event: The event type
+ *
+ * Clients should not be concerned about wake line behavior. However, due
+ * to a race condition in HSI HW protocol, clients need to be notified
+ * about wake line changes, so they can implement a workaround for it.
+ *
+ * Events:
+ * HSI_EVENT_START_RX - Incoming wake line high
+ * HSI_EVENT_STOP_RX - Incoming wake line down
+ */
+void hsi_event(struct hsi_port *port, unsigned int event)
+{
+	int (*fn)(struct hsi_client *cl, void *data);
+
+	switch (event) {
+	case HSI_EVENT_START_RX:
+		fn = hsi_start_rx;
+		break;
+	case HSI_EVENT_STOP_RX:
+		fn = hsi_stop_rx;
+		break;
+	default:
+		return;
+	}
+	hsi_port_for_each_client(port, NULL, fn);
+}
+EXPORT_SYMBOL_GPL(hsi_event);
+
+static int __init hsi_init(void)
+{
+	return bus_register(&hsi_bus_type);
+}
+postcore_initcall(hsi_init);
+
+static void __exit hsi_exit(void)
+{
+	bus_unregister(&hsi_bus_type);
+}
+module_exit(hsi_exit);
+
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi_boardinfo.c b/drivers/hsi/hsi_boardinfo.c
new file mode 100644
index 0000000..e56bc6d
--- /dev/null
+++ b/drivers/hsi/hsi_boardinfo.c
@@ -0,0 +1,62 @@
+/*
+ * HSI clients registration interface
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "hsi_core.h"
+
+/*
+ * hsi_board_list is only used internally by the HSI framework.
+ * No one else is allowed to make use of it.
+ */
+LIST_HEAD(hsi_board_list);
+EXPORT_SYMBOL_GPL(hsi_board_list);
+
+/**
+ * hsi_register_board_info - Register HSI clients information
+ * @info: Array of HSI clients on the board
+ * @len: Length of the array
+ *
+ * HSI clients are statically declared and registered on board files.
+ *
+ * HSI clients will be automatically registered to the HSI bus once the
+ * controller and the port where the clients wishes to attach are registered
+ * to it.
+ *
+ * Return -errno on failure, 0 on success.
+ */
+int __init hsi_register_board_info(struct hsi_board_info const *info,
+							unsigned int len)
+{
+	struct hsi_cl_info *cl_info;
+
+	cl_info = kzalloc(sizeof(*cl_info) * len, GFP_KERNEL);
+	if (!cl_info)
+		return -ENOMEM;
+
+	for (; len; len--, info++, cl_info++) {
+		cl_info->info = *info;
+		list_add_tail(&cl_info->list, &hsi_board_list);
+	}
+
+	return 0;
+}
diff --git a/drivers/hsi/hsi_core.h b/drivers/hsi/hsi_core.h
new file mode 100644
index 0000000..ab5c2fb
--- /dev/null
+++ b/drivers/hsi/hsi_core.h
@@ -0,0 +1,35 @@
+/*
+ * HSI framework internal interfaces,
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_CORE_H__
+#define __LINUX_HSI_CORE_H__
+
+#include <linux/hsi/hsi.h>
+
+struct hsi_cl_info {
+	struct list_head	list;
+	struct hsi_board_info	info;
+};
+
+extern struct list_head hsi_board_list;
+
+#endif /* __LINUX_HSI_CORE_H__ */
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 3b728e8..e08f757 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -763,10 +763,18 @@ static ssize_t store_bank1_setting(struct device *dev, struct device_attribute
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	u8 val = (simple_strtoul(buf, NULL, 10) * 255 +
-		data->bank1_max_value[attr->index]/2) /
+	unsigned long val;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	ret = count;
+	val = (val * 255 + data->bank1_max_value[attr->index] / 2) /
 		data->bank1_max_value[attr->index];
-	ssize_t ret = count;
+	if (val > 255)
+		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
 	if (data->bank1_settings[attr->index][attr->nr] != val) {
@@ -788,13 +796,19 @@ static ssize_t store_bank2_setting(struct device *dev, struct device_attribute
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) /
-		ABIT_UGURU_FAN_MAX;
-	ssize_t ret = count;
+	unsigned long val;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	ret = count;
+	val = (val * 255 + ABIT_UGURU_FAN_MAX / 2) / ABIT_UGURU_FAN_MAX;
 
 	/* this check can be done before taking the lock */
-	if ((val < abituguru_bank2_min_threshold) ||
-			(val > abituguru_bank2_max_threshold))
+	if (val < abituguru_bank2_min_threshold ||
+			val > abituguru_bank2_max_threshold)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -871,10 +885,15 @@ static ssize_t store_bank1_mask(struct device *dev,
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	int mask = simple_strtoul(buf, NULL, 10);
-	ssize_t ret = count;
+	ssize_t ret;
 	u8 orig_val;
+	unsigned long mask;
+
+	ret = kstrtoul(buf, 10, &mask);
+	if (ret)
+		return ret;
 
+	ret = count;
 	mutex_lock(&data->update_lock);
 	orig_val = data->bank1_settings[attr->index][0];
 
@@ -899,10 +918,15 @@ static ssize_t store_bank2_mask(struct device *dev,
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	int mask = simple_strtoul(buf, NULL, 10);
-	ssize_t ret = count;
+	ssize_t ret;
 	u8 orig_val;
+	unsigned long mask;
+
+	ret = kstrtoul(buf, 10, &mask);
+	if (ret)
+		return ret;
 
+	ret = count;
 	mutex_lock(&data->update_lock);
 	orig_val = data->bank2_settings[attr->index][0];
 
@@ -937,10 +961,17 @@ static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	u8 min, val = (simple_strtoul(buf, NULL, 10) +
-		abituguru_pwm_settings_multiplier[attr->nr]/2) /
-		abituguru_pwm_settings_multiplier[attr->nr];
-	ssize_t ret = count;
+	u8 min;
+	unsigned long val;
+	ssize_t ret;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	ret = count;
+	val = (val + abituguru_pwm_settings_multiplier[attr->nr] / 2) /
+				abituguru_pwm_settings_multiplier[attr->nr];
 
 	/* special case pwm1 min pwm% */
 	if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2)))
@@ -949,7 +980,7 @@ static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
 		min = abituguru_pwm_min[attr->nr];
 
 	/* this check can be done before taking the lock */
-	if ((val < min) || (val > abituguru_pwm_max[attr->nr]))
+	if (val < min || val > abituguru_pwm_max[attr->nr])
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -996,27 +1027,32 @@ static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10) - 1;
-	ssize_t ret = count;
+	ssize_t ret;
+	unsigned long val;
+	u8 orig_val;
+	u8 address;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret)
+		return ret;
+
+	if (val == 0 || val > data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR])
+		return -EINVAL;
 
+	val -= 1;
+	ret = count;
 	mutex_lock(&data->update_lock);
-	if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
-		u8 orig_val = data->pwm_settings[attr->index][0];
-		u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val];
-		data->pwm_settings[attr->index][0] &= 0xF0;
-		data->pwm_settings[attr->index][0] |= address;
-		if (data->pwm_settings[attr->index][0] != orig_val) {
-			if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
-					attr->index,
-					data->pwm_settings[attr->index],
-					5) < 1) {
-				data->pwm_settings[attr->index][0] = orig_val;
-				ret = -EIO;
-			}
+	orig_val = data->pwm_settings[attr->index][0];
+	address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val];
+	data->pwm_settings[attr->index][0] &= 0xF0;
+	data->pwm_settings[attr->index][0] |= address;
+	if (data->pwm_settings[attr->index][0] != orig_val) {
+		if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, attr->index,
+				    data->pwm_settings[attr->index], 5) < 1) {
+			data->pwm_settings[attr->index][0] = orig_val;
+			ret = -EIO;
 		}
 	}
-	else
-		ret = -EINVAL;
 	mutex_unlock(&data->update_lock);
 	return ret;
 }
@@ -1037,22 +1073,27 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
 {
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct abituguru_data *data = dev_get_drvdata(dev);
-	u8 orig_val, user_val = simple_strtoul(buf, NULL, 10);
-	ssize_t ret = count;
+	u8 orig_val;
+	ssize_t ret;
+	unsigned long user_val;
 
+	ret = kstrtoul(buf, 10, &user_val);
+	if (ret)
+		return ret;
+
+	ret = count;
 	mutex_lock(&data->update_lock);
 	orig_val = data->pwm_settings[attr->index][0];
 	switch (user_val) {
-		case 0:
-			data->pwm_settings[attr->index][0] &=
-				~ABIT_UGURU_FAN_PWM_ENABLE;
-			break;
-		case 2:
-			data->pwm_settings[attr->index][0] |=
-				ABIT_UGURU_FAN_PWM_ENABLE;
-			break;
-		default:
-			ret = -EINVAL;
+	case 0:
+		data->pwm_settings[attr->index][0] &=
+			~ABIT_UGURU_FAN_PWM_ENABLE;
+		break;
+	case 2:
+		data->pwm_settings[attr->index][0] |= ABIT_UGURU_FAN_PWM_ENABLE;
+		break;
+	default:
+		ret = -EINVAL;
 	}
 	if ((data->pwm_settings[attr->index][0] != orig_val) &&
 			(abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
@@ -1153,7 +1194,8 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
 		0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02,
 		0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C };
 
-	if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL)))
+	data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
 	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
@@ -1332,24 +1374,26 @@ static struct abituguru_data *abituguru_update_device(struct device *dev)
 	mutex_lock(&data->update_lock);
 	if (time_after(jiffies, data->last_updated + HZ)) {
 		success = 0;
-		if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
-				data->alarms, 3, 0)) != 3)
+		err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
+				     data->alarms, 3, 0);
+		if (err != 3)
 			goto LEAVE_UPDATE;
 		for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
-			if ((err = abituguru_read(data,
-					ABIT_UGURU_SENSOR_BANK1, i,
-					&data->bank1_value[i], 1, 0)) != 1)
+			err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1,
+					     i, &data->bank1_value[i], 1, 0);
+			if (err != 1)
 				goto LEAVE_UPDATE;
-			if ((err = abituguru_read(data,
-					ABIT_UGURU_SENSOR_BANK1 + 1, i,
-					data->bank1_settings[i], 3, 0)) != 3)
+			err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
+					     i, data->bank1_settings[i], 3, 0);
+			if (err != 3)
 				goto LEAVE_UPDATE;
 		}
-		for (i = 0; i < data->bank2_sensors; i++)
-			if ((err = abituguru_read(data,
-					ABIT_UGURU_SENSOR_BANK2, i,
-					&data->bank2_value[i], 1, 0)) != 1)
+		for (i = 0; i < data->bank2_sensors; i++) {
+			err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i,
+					     &data->bank2_value[i], 1, 0);
+			if (err != 1)
 				goto LEAVE_UPDATE;
+		}
 		/* success! */
 		success = 1;
 		data->update_timeouts = 0;
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 34a14a7..93ab1a5 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -80,7 +80,8 @@
 #define ABIT_UGURU3_MAX_NO_SENSORS 26
 /* sum of strlen +1 of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
    in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0, in??_label\0 */
-#define ABIT_UGURU3_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
+#define ABIT_UGURU3_IN_NAMES_LENGTH \
+				(11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
 /* sum of strlen +1 of: temp??_input\0, temp??_max\0, temp??_crit\0,
    temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0,
    temp??_label\0 */
@@ -112,7 +113,7 @@
 
 /* Structures */
 struct abituguru3_sensor_info {
-	const char* name;
+	const char *name;
 	int port;
 	int type;
 	int multiplier;
@@ -659,34 +660,39 @@ static int abituguru3_synchronize(struct abituguru3_data *data)
 {
 	int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT;
 
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("synchronize timeout during initial busy "
 			"wait, status: 0x%02x\n", x);
 		return -EIO;
 	}
 
 	outb(0x20, data->addr + ABIT_UGURU3_DATA);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, "
 			"status: 0x%02x\n", x);
 		return -EIO;
 	}
 
 	outb(0x10, data->addr + ABIT_UGURU3_CMD);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, "
 			"status: 0x%02x\n", x);
 		return -EIO;
 	}
 
 	outb(0x00, data->addr + ABIT_UGURU3_CMD);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, "
 			"status: 0x%02x\n", x);
 		return -EIO;
 	}
 
-	if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_for_read(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, "
 			"status: 0x%02x\n", x);
 		return -EIO;
@@ -712,11 +718,13 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
 {
 	int i, x;
 
-	if ((x = abituguru3_synchronize(data)))
+	x = abituguru3_synchronize(data);
+	if (x)
 		return x;
 
 	outb(0x1A, data->addr + ABIT_UGURU3_DATA);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
 			"sending 0x1A, status: 0x%02x\n", (unsigned int)bank,
 			(unsigned int)offset, x);
@@ -724,7 +732,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
 	}
 
 	outb(bank, data->addr + ABIT_UGURU3_CMD);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
 			"sending the bank, status: 0x%02x\n",
 			(unsigned int)bank, (unsigned int)offset, x);
@@ -732,7 +741,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
 	}
 
 	outb(offset, data->addr + ABIT_UGURU3_CMD);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
 			"sending the offset, status: 0x%02x\n",
 			(unsigned int)bank, (unsigned int)offset, x);
@@ -740,7 +750,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
 	}
 
 	outb(count, data->addr + ABIT_UGURU3_CMD);
-	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+	x = abituguru3_wait_while_busy(data);
+	if (x != ABIT_UGURU3_SUCCESS) {
 		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
 			"sending the count, status: 0x%02x\n",
 			(unsigned int)bank, (unsigned int)offset, x);
@@ -748,8 +759,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
 	}
 
 	for (i = 0; i < count; i++) {
-		if ((x = abituguru3_wait_for_read(data)) !=
-				ABIT_UGURU3_SUCCESS) {
+		x = abituguru3_wait_for_read(data);
+		if (x != ABIT_UGURU3_SUCCESS) {
 			ABIT_UGURU3_DEBUG("timeout reading byte %d from "
 				"0x%02x:0x%02x, status: 0x%02x\n", i,
 				(unsigned int)bank, (unsigned int)offset, x);
@@ -768,13 +779,15 @@ static int abituguru3_read_increment_offset(struct abituguru3_data *data,
 {
 	int i, x;
 
-	for (i = 0; i < offset_count; i++)
-		if ((x = abituguru3_read(data, bank, offset + i, count,
-				buf + i * count)) != count) {
+	for (i = 0; i < offset_count; i++) {
+		x = abituguru3_read(data, bank, offset + i, count,
+				    buf + i * count);
+		if (x != count) {
 			if (x < 0)
 				return x;
 			return i * count + x;
 		}
+	}
 
 	return i * count;
 }
@@ -923,7 +936,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
 	u8 buf[2];
 	u16 id;
 
-	if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL)))
+	data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
 	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
@@ -931,10 +945,10 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, data);
 
 	/* Read the motherboard ID */
-	if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK,
-			ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) {
+	i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK, ABIT_UGURU3_BOARD_ID,
+			    2, buf);
+	if (i != 2)
 		goto abituguru3_probe_error;
-	}
 
 	/* Completely read the uGuru to see if one really is there */
 	if (!abituguru3_update_device(&pdev->dev))
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index df29a7f..edbdb6d 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -130,7 +130,11 @@ static ssize_t set_max_min(struct device *dev,
 	struct ad7414_data *data = i2c_get_clientdata(client);
 	int index = to_sensor_dev_attr(attr)->index;
 	u8 reg = AD7414_REG_LIMIT[index];
-	long temp = simple_strtol(buf, NULL, 10);
+	long temp;
+	int ret = kstrtol(buf, 10, &temp);
+
+	if (ret < 0)
+		return ret;
 
 	temp = SENSORS_LIMIT(temp, -40000, 85000);
 	temp = (temp + (temp < 0 ? -500 : 500)) / 1000;
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index 8cb718c..42461d1 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -167,7 +167,11 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct ad7418_data *data = i2c_get_clientdata(client);
-	long temp = simple_strtol(buf, NULL, 10);
+	long temp;
+	int ret = kstrtol(buf, 10, &temp);
+
+	if (ret < 0)
+		return ret;
 
 	mutex_lock(&data->lock);
 	data->temp[attr->index] = LM75_TEMP_TO_REG(temp);
@@ -228,7 +232,8 @@ static int ad7418_probe(struct i2c_client *client,
 		goto exit;
 	}
 
-	if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit;
 	}
@@ -261,7 +266,8 @@ static int ad7418_probe(struct i2c_client *client,
 	ad7418_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
+	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c
index 0158cc3..e6fc006 100644
--- a/drivers/hwmon/adm1021.c
+++ b/drivers/hwmon/adm1021.c
@@ -182,7 +182,13 @@ static ssize_t set_temp_max(struct device *dev,
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1021_data *data = i2c_get_clientdata(client);
-	long temp = simple_strtol(buf, NULL, 10) / 1000;
+	long temp;
+	int err;
+
+	err = kstrtol(buf, 10, &temp);
+	if (err)
+		return err;
+	temp /= 1000;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127);
@@ -201,7 +207,13 @@ static ssize_t set_temp_min(struct device *dev,
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1021_data *data = i2c_get_clientdata(client);
-	long temp = simple_strtol(buf, NULL, 10) / 1000;
+	long temp;
+	int err;
+
+	err = kstrtol(buf, 10, &temp);
+	if (err)
+		return err;
+	temp /= 1000;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[index] = SENSORS_LIMIT(temp, -128, 127);
@@ -226,7 +238,14 @@ static ssize_t set_low_power(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1021_data *data = i2c_get_clientdata(client);
-	int low_power = simple_strtol(buf, NULL, 10) != 0;
+	char low_power;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	low_power = val != 0;
 
 	mutex_lock(&data->update_lock);
 	if (low_power != data->low_power) {
@@ -361,7 +380,8 @@ static int adm1021_probe(struct i2c_client *client,
 		adm1021_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group)))
+	err = sysfs_create_group(&client->dev.kobj, &adm1021_group);
+	if (err)
 		goto error1;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
@@ -461,7 +481,7 @@ static void __exit sensors_adm1021_exit(void)
 	i2c_del_driver(&adm1021_driver);
 }
 
-MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
 		"Philip Edelbrock <phil@netroedge.com>");
 MODULE_DESCRIPTION("adm1021 driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c
index 60befc0..14d8997 100644
--- a/drivers/hwmon/adm1025.c
+++ b/drivers/hwmon/adm1025.c
@@ -12,7 +12,7 @@
  * resolution of about 0.5% of the nominal value). Temperature values are
  * reported with a 1 deg resolution and a 3 deg accuracy. Complete
  * datasheet can be obtained from Analog's website at:
- *   http://www.onsemi.com/PowerSolutions/product.do?id=ADM1025 
+ *   http://www.onsemi.com/PowerSolutions/product.do?id=ADM1025
  *
  * This driver also supports the ADM1025A, which differs from the ADM1025
  * only in that it has "open-drain VID inputs while the ADM1025 has
@@ -91,15 +91,16 @@ enum chips { adm1025, ne1619 };
 
 static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 };
 
-#define IN_FROM_REG(reg,scale)	(((reg) * (scale) + 96) / 192)
-#define IN_TO_REG(val,scale)	((val) <= 0 ? 0 : \
+#define IN_FROM_REG(reg, scale)	(((reg) * (scale) + 96) / 192)
+#define IN_TO_REG(val, scale)	((val) <= 0 ? 0 : \
 				 (val) * 192 >= (scale) * 255 ? 255 : \
-				 ((val) * 192 + (scale)/2) / (scale))
+				 ((val) * 192 + (scale) / 2) / (scale))
 
 #define TEMP_FROM_REG(reg)	((reg) * 1000)
 #define TEMP_TO_REG(val)	((val) <= -127500 ? -128 : \
 				 (val) >= 126500 ? 127 : \
-				 (((val) < 0 ? (val)-500 : (val)+500) / 1000))
+				 (((val) < 0 ? (val) - 500 : \
+				   (val) + 500) / 1000))
 
 /*
  * Functions declaration
@@ -218,7 +219,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	int index = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1025_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[index] = IN_TO_REG(val, in_scale[index]);
@@ -234,7 +240,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	int index = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1025_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[index] = IN_TO_REG(val, in_scale[index]);
@@ -264,7 +275,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	int index = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1025_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[index] = TEMP_TO_REG(val);
@@ -280,7 +296,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	int index = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1025_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[index] = TEMP_TO_REG(val);
@@ -343,7 +364,14 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
 	struct adm1025_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
@@ -462,14 +490,15 @@ static int adm1025_probe(struct i2c_client *client,
 	adm1025_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
+	err = sysfs_create_group(&client->dev.kobj, &adm1025_group);
+	if (err)
 		goto exit_free;
 
 	/* Pin 11 is either in4 (+12V) or VID4 */
 	config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
 	if (!(config & 0x20)) {
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					      &adm1025_group_in4)))
+		err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4);
+		if (err)
 			goto exit_remove;
 	}
 
@@ -506,7 +535,7 @@ static void adm1025_init_client(struct i2c_client *client)
 	 * setting yet, we better set the high limits to the max so that
 	 * no alarm triggers.
 	 */
-	for (i=0; i<6; i++) {
+	for (i = 0; i < 6; i++) {
 		reg = i2c_smbus_read_byte_data(client,
 					       ADM1025_REG_IN_MAX(i));
 		if (reg == 0)
@@ -514,7 +543,7 @@ static void adm1025_init_client(struct i2c_client *client)
 						  ADM1025_REG_IN_MAX(i),
 						  0xFF);
 	}
-	for (i=0; i<2; i++) {
+	for (i = 0; i < 2; i++) {
 		reg = i2c_smbus_read_byte_data(client,
 					       ADM1025_REG_TEMP_HIGH(i));
 		if (reg == 0)
@@ -555,7 +584,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
 		int i;
 
 		dev_dbg(&client->dev, "Updating data.\n");
-		for (i=0; i<6; i++) {
+		for (i = 0; i < 6; i++) {
 			data->in[i] = i2c_smbus_read_byte_data(client,
 				      ADM1025_REG_IN(i));
 			data->in_min[i] = i2c_smbus_read_byte_data(client,
@@ -563,7 +592,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
 			data->in_max[i] = i2c_smbus_read_byte_data(client,
 					  ADM1025_REG_IN_MAX(i));
 		}
-		for (i=0; i<2; i++) {
+		for (i = 0; i < 2; i++) {
 			data->temp[i] = i2c_smbus_read_byte_data(client,
 					ADM1025_REG_TEMP(i));
 			data->temp_min[i] = i2c_smbus_read_byte_data(client,
diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c
index 0531867..cd773ce 100644
--- a/drivers/hwmon/adm1026.c
+++ b/drivers/hwmon/adm1026.c
@@ -202,18 +202,19 @@ static int adm1026_scaling[] = { /* .001 Volts */
  *      22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000
  */
 #define FAN_TO_REG(val, div)  ((val) <= 0 ? 0xff : \
-				SENSORS_LIMIT(1350000/((val)*(div)), 1, 254))
-#define FAN_FROM_REG(val, div) ((val) == 0 ? -1:(val) == 0xff ? 0 : \
-				1350000/((val)*(div)))
-#define DIV_FROM_REG(val) (1<<(val))
+				SENSORS_LIMIT(1350000 / ((val) * (div)), \
+					      1, 254))
+#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \
+				1350000 / ((val) * (div)))
+#define DIV_FROM_REG(val) (1 << (val))
 #define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
 
 /* Temperature is reported in 1 degC increments */
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
-	-127, 127))
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
+					/ 1000, -127, 127))
 #define TEMP_FROM_REG(val) ((val) * 1000)
-#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val)+((val)<0 ? -500 : 500))/1000,\
-	-127, 127))
+#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \
+					  / 1000, -127, 127))
 #define OFFSET_FROM_REG(val) ((val) * 1000)
 
 #define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255))
@@ -226,8 +227,8 @@ static int adm1026_scaling[] = { /* .001 Volts */
  *   indicates that the DAC could be used to drive the fans, but in our
  *   example board (Arima HDAMA) it isn't connected to the fans at all.
  */
-#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val)*255)+500)/2500), 0, 255))
-#define DAC_FROM_REG(val) (((val)*2500)/255)
+#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val) * 255) + 500) / 2500), 0, 255))
+#define DAC_FROM_REG(val) (((val) * 2500) / 255)
 
 /* Chip sampling rates
  *
@@ -388,17 +389,16 @@ static void adm1026_init_client(struct i2c_client *client)
 		dev_dbg(&client->dev, "THERM pin enabled.  "
 			"GPIO16 disabled.\n");
 	}
-	if (data->config3 & CFG3_VREF_250) {
+	if (data->config3 & CFG3_VREF_250)
 		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
-	} else {
+	else
 		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
-	}
 	/* Read and pick apart the existing GPIO configuration */
 	value = 0;
-	for (i = 0;i <= 15;++i) {
+	for (i = 0; i <= 15; ++i) {
 		if ((i & 0x03) == 0) {
 			value = adm1026_read_value(client,
-					ADM1026_REG_GPIO_CFG_0_3 + i/4);
+					ADM1026_REG_GPIO_CFG_0_3 + i / 4);
 		}
 		data->gpio_config[i] = value & 0x03;
 		value >>= 2;
@@ -428,7 +428,7 @@ static void adm1026_init_client(struct i2c_client *client)
 	 *   without first setting a value for pwm1.auto_pwm_min
 	 *   will not result in potentially dangerous fan speed decrease.
 	 */
-	data->pwm1.auto_pwm_min=255;
+	data->pwm1.auto_pwm_min = 255;
 	/* Start monitoring */
 	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
 	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
@@ -440,7 +440,7 @@ static void adm1026_init_client(struct i2c_client *client)
 	/* initialize fan_div[] to hardware defaults */
 	value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) |
 		(adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8);
-	for (i = 0;i <= 7;++i) {
+	for (i = 0; i <= 7; ++i) {
 		data->fan_div[i] = DIV_FROM_REG(value & 0x03);
 		value >>= 2;
 	}
@@ -452,7 +452,7 @@ static void adm1026_print_gpio(struct i2c_client *client)
 	int i;
 
 	dev_dbg(&client->dev, "GPIO config is:\n");
-	for (i = 0;i <= 7;++i) {
+	for (i = 0; i <= 7; ++i) {
 		if (data->config2 & (1 << i)) {
 			dev_dbg(&client->dev, "\t%sGP%s%d\n",
 				data->gpio_config[i] & 0x02 ? "" : "!",
@@ -462,7 +462,7 @@ static void adm1026_print_gpio(struct i2c_client *client)
 			dev_dbg(&client->dev, "\tFAN%d\n", i);
 		}
 	}
-	for (i = 8;i <= 15;++i) {
+	for (i = 8; i <= 15; ++i) {
 		dev_dbg(&client->dev, "\t%sGP%s%d\n",
 			data->gpio_config[i] & 0x02 ? "" : "!",
 			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
@@ -491,46 +491,39 @@ static void adm1026_fixup_gpio(struct i2c_client *client)
 	 */
 
 	/* Make outputs */
-	for (i = 0;i <= 16;++i) {
-		if (gpio_output[i] >= 0 && gpio_output[i] <= 16) {
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_output[i] >= 0 && gpio_output[i] <= 16)
 			data->gpio_config[gpio_output[i]] |= 0x01;
-		}
 		/* if GPIO0-7 is output, it isn't a FAN tach */
-		if (gpio_output[i] >= 0 && gpio_output[i] <= 7) {
+		if (gpio_output[i] >= 0 && gpio_output[i] <= 7)
 			data->config2 |= 1 << gpio_output[i];
-		}
 	}
 
 	/* Input overrides output */
-	for (i = 0;i <= 16;++i) {
-		if (gpio_input[i] >= 0 && gpio_input[i] <= 16) {
-			data->gpio_config[gpio_input[i]] &= ~ 0x01;
-		}
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_input[i] >= 0 && gpio_input[i] <= 16)
+			data->gpio_config[gpio_input[i]] &= ~0x01;
 		/* if GPIO0-7 is input, it isn't a FAN tach */
-		if (gpio_input[i] >= 0 && gpio_input[i] <= 7) {
+		if (gpio_input[i] >= 0 && gpio_input[i] <= 7)
 			data->config2 |= 1 << gpio_input[i];
-		}
 	}
 
 	/* Inverted */
-	for (i = 0;i <= 16;++i) {
-		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) {
-			data->gpio_config[gpio_inverted[i]] &= ~ 0x02;
-		}
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16)
+			data->gpio_config[gpio_inverted[i]] &= ~0x02;
 	}
 
 	/* Normal overrides inverted */
-	for (i = 0;i <= 16;++i) {
-		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) {
+	for (i = 0; i <= 16; ++i) {
+		if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16)
 			data->gpio_config[gpio_normal[i]] |= 0x02;
-		}
 	}
 
 	/* Fan overrides input and output */
-	for (i = 0;i <= 7;++i) {
-		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) {
+	for (i = 0; i <= 7; ++i) {
+		if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7)
 			data->config2 &= ~(1 << gpio_fan[i]);
-		}
 	}
 
 	/* Write new configs to registers */
@@ -538,7 +531,7 @@ static void adm1026_fixup_gpio(struct i2c_client *client)
 	data->config3 = (data->config3 & 0x3f)
 			| ((data->gpio_config[16] & 0x03) << 6);
 	adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3);
-	for (i = 15, value = 0;i >= 0;--i) {
+	for (i = 15, value = 0; i >= 0; --i) {
 		value <<= 2;
 		value |= data->gpio_config[i] & 0x03;
 		if ((i & 0x03) == 0) {
@@ -563,20 +556,21 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
 
 	mutex_lock(&data->update_lock);
 	if (!data->valid
-	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
+	    || time_after(jiffies,
+			  data->last_reading + ADM1026_DATA_INTERVAL)) {
 		/* Things that change quickly */
 		dev_dbg(&client->dev, "Reading sensor values\n");
-		for (i = 0;i <= 16;++i) {
+		for (i = 0; i <= 16; ++i) {
 			data->in[i] =
 			    adm1026_read_value(client, ADM1026_REG_IN[i]);
 		}
 
-		for (i = 0;i <= 7;++i) {
+		for (i = 0; i <= 7; ++i) {
 			data->fan[i] =
 			    adm1026_read_value(client, ADM1026_REG_FAN(i));
 		}
 
-		for (i = 0;i <= 2;++i) {
+		for (i = 0; i <= 2; ++i) {
 			/* NOTE: temp[] is s8 and we assume 2's complement
 			 *   "conversion" in the assignment */
 			data->temp[i] =
@@ -614,7 +608,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
 	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
 		/* Things that don't change often */
 		dev_dbg(&client->dev, "Reading config values\n");
-		for (i = 0;i <= 16;++i) {
+		for (i = 0; i <= 16; ++i) {
 			data->in_min[i] = adm1026_read_value(client,
 				ADM1026_REG_IN_MIN[i]);
 			data->in_max[i] = adm1026_read_value(client,
@@ -624,7 +618,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
 		value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3)
 			| (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7)
 			<< 8);
-		for (i = 0;i <= 7;++i) {
+		for (i = 0; i <= 7; ++i) {
 			data->fan_min[i] = adm1026_read_value(client,
 				ADM1026_REG_FAN_MIN(i));
 			data->fan_div[i] = DIV_FROM_REG(value & 0x03);
@@ -681,7 +675,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
 		data->gpio_config[16] = (data->config3 >> 6) & 0x03;
 
 		value = 0;
-		for (i = 0;i <= 15;++i) {
+		for (i = 0; i <= 15; ++i) {
 			if ((i & 0x03) == 0) {
 				value = adm1026_read_value(client,
 					    ADM1026_REG_GPIO_CFG_0_3 + i/4);
@@ -721,7 +715,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = INS_TO_REG(nr, val);
@@ -744,7 +743,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = INS_TO_REG(nr, val);
@@ -779,23 +783,31 @@ in_reg(13);
 in_reg(14);
 in_reg(15);
 
-static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_in16(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) -
 		NEG12_OFFSET);
 }
-static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16])
 		- NEG12_OFFSET);
 }
-static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
@@ -803,17 +815,24 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16])
 			- NEG12_OFFSET);
 }
-static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
@@ -823,10 +842,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, c
 }
 
 static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
-static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
-static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
-
-
+static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min,
+			  set_in16_min, 16);
+static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max,
+			  set_in16_max, 16);
 
 
 /* Now add fan read/write functions */
@@ -856,7 +875,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]);
@@ -890,9 +914,8 @@ static void fixup_fan_min(struct device *dev, int fan, int old_div)
 	int new_div = data->fan_div[fan];
 
 	/* 0 and 0xff are special.  Don't adjust them */
-	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) {
+	if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff)
 		return;
-	}
 
 	new_min = data->fan_min[fan] * old_div / new_div;
 	new_min = SENSORS_LIMIT(new_min, 1, 254);
@@ -916,9 +939,14 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val, orig_div, new_div;
+	long val;
+	int orig_div, new_div;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtol(buf, NULL, 10);
 	new_div = DIV_TO_REG(val);
 
 	mutex_lock(&data->update_lock);
@@ -939,9 +967,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 				    (DIV_TO_REG(data->fan_div[7]) << 6));
 	}
 
-	if (data->fan_div[nr] != orig_div) {
+	if (data->fan_div[nr] != orig_div)
 		fixup_fan_min(dev, nr, orig_div);
-	}
+
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -983,7 +1011,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = TEMP_TO_REG(val);
@@ -1007,7 +1040,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = TEMP_TO_REG(val);
@@ -1046,7 +1084,12 @@ static ssize_t set_temp_offset(struct device *dev,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_offset[nr] = TEMP_TO_REG(val);
@@ -1056,8 +1099,8 @@ static ssize_t set_temp_offset(struct device *dev,
 	return count;
 }
 
-#define temp_offset_reg(offset)							\
-static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,		\
+#define temp_offset_reg(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,	\
 		show_temp_offset, set_temp_offset, offset - 1);
 
 temp_offset_reg(1);
@@ -1097,7 +1140,12 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_tmin[nr] = TEMP_TO_REG(val);
@@ -1131,15 +1179,21 @@ static ssize_t set_temp_crit_enable(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (val > 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
+	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
+	mutex_unlock(&data->update_lock);
 
-	if ((val == 1) || (val==0)) {
-		mutex_lock(&data->update_lock);
-		data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4);
-		adm1026_write_value(client, ADM1026_REG_CONFIG1,
-			data->config1);
-		mutex_unlock(&data->update_lock);
-	}
 	return count;
 }
 
@@ -1166,7 +1220,12 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_crit[nr] = TEMP_TO_REG(val);
@@ -1184,17 +1243,24 @@ temp_crit_reg(1);
 temp_crit_reg(2);
 temp_crit_reg(3);
 
-static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_analog_out_reg(struct device *dev,
+				   struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out));
 }
-static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+static ssize_t set_analog_out_reg(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->analog_out = DAC_TO_REG(val);
@@ -1206,7 +1272,8 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a
 static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
 	set_analog_out_reg);
 
-static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	int vid = (data->gpio >> 11) & 0x1f;
@@ -1214,25 +1281,35 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
 	dev_dbg(dev, "Setting VID from GPIO11-15.\n");
 	return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm));
 }
+
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
-static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct adm1026_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
-static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+
+static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct adm1026_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	data->vrm = simple_strtol(buf, NULL, 10);
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
-static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms_reg(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%ld\n", data->alarms);
@@ -1277,18 +1354,24 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24);
 static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25);
 static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26);
 
-static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarm_mask(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%ld\n", data->alarm_mask);
 }
-static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
 	unsigned long mask;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->alarm_mask = val & 0x7fffffff;
@@ -1313,18 +1396,24 @@ static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
 	set_alarm_mask);
 
 
-static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%ld\n", data->gpio);
 }
-static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+static ssize_t set_gpio(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
 	long gpio;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->gpio = val & 0x1ffff;
@@ -1340,19 +1429,24 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const
 
 static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
 
-
-static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%ld\n", data->gpio_mask);
 }
-static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
 	long mask;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->gpio_mask = val & 0x1ffff;
@@ -1368,19 +1462,26 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
 
-static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr,
+			    char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm));
 }
-static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+
+static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 
 	if (data->pwm1.enable == 1) {
-		int val = simple_strtol(buf, NULL, 10);
+		long val;
+		int err;
+
+		err = kstrtol(buf, 10, &val);
+		if (err)
+			return err;
 
 		mutex_lock(&data->update_lock);
 		data->pwm1.pwm = PWM_TO_REG(val);
@@ -1389,17 +1490,26 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co
 	}
 	return count;
 }
-static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
+
+static ssize_t show_auto_pwm_min(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min);
 }
-static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+
+static ssize_t set_auto_pwm_min(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255);
@@ -1411,44 +1521,53 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
+
+static ssize_t show_auto_pwm_max(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", ADM1026_PWM_MAX);
 }
-static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
+
+static ssize_t show_pwm_enable(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%d\n", data->pwm1.enable);
 }
-static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
 	int old_enable;
+	unsigned long val;
+	int err;
 
-	if ((val >= 0) && (val < 3)) {
-		mutex_lock(&data->update_lock);
-		old_enable = data->pwm1.enable;
-		data->pwm1.enable = val;
-		data->config1 = (data->config1 & ~CFG1_PWM_AFC)
-				| ((val == 2) ? CFG1_PWM_AFC : 0);
-		adm1026_write_value(client, ADM1026_REG_CONFIG1,
-			data->config1);
-		if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
-			data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
-				PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
-			adm1026_write_value(client, ADM1026_REG_PWM,
-				data->pwm1.pwm);
-		} else if (!((old_enable == 1) && (val == 1))) {
-			/* set pwm to safe value */
-			data->pwm1.pwm = 255;
-			adm1026_write_value(client, ADM1026_REG_PWM,
-				data->pwm1.pwm);
-		}
-		mutex_unlock(&data->update_lock);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (val >= 3)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	old_enable = data->pwm1.enable;
+	data->pwm1.enable = val;
+	data->config1 = (data->config1 & ~CFG1_PWM_AFC)
+			| ((val == 2) ? CFG1_PWM_AFC : 0);
+	adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1);
+	if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */
+		data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) |
+			PWM_MIN_TO_REG(data->pwm1.auto_pwm_min));
+		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
+	} else if (!((old_enable == 1) && (val == 1))) {
+		/* set pwm to safe value */
+		data->pwm1.pwm = 255;
+		adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm);
 	}
+	mutex_unlock(&data->update_lock);
+
 	return count;
 }
 
@@ -1716,7 +1835,8 @@ static int adm1026_probe(struct i2c_client *client,
 	adm1026_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
+	err = sysfs_create_group(&client->dev.kobj, &adm1026_group);
+	if (err)
 		goto exitfree;
 	if (data->config1 & CFG1_AIN8_9)
 		err = sysfs_create_group(&client->dev.kobj,
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 0b8a3b1..d789c33 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -78,7 +78,7 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
 
 #define TEMP_FROM_REG(val)	((val) * 1000)
 
-#define DIV_FROM_REG(val)	( 1 << (((val) >> 6) - 1))
+#define DIV_FROM_REG(val)	(1 << (((val) >> 6) - 1))
 
 /* Registers to be checked by adm1029_update_device() */
 static const u8 ADM1029_REG_TEMP[] = {
@@ -200,8 +200,11 @@ static ssize_t set_fan_div(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1029_data *data = i2c_get_clientdata(client);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	long val = simple_strtol(buf, NULL, 10);
 	u8 reg;
+	long val;
+	int ret = kstrtol(buf, 10, &val);
+	if (ret < 0)
+		return ret;
 
 	mutex_lock(&data->update_lock);
 
@@ -355,7 +358,8 @@ static int adm1029_probe(struct i2c_client *client,
 	}
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
+	err = sysfs_create_group(&client->dev.kobj, &adm1029_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 3f63f5f..2de4511 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -1,12 +1,12 @@
 /*
  * adm9240.c	Part of lm_sensors, Linux kernel modules for hardware
- * 		monitoring
+ *		monitoring
  *
  * Copyright (C) 1999	Frodo Looijaard <frodol@dds.nl>
  *			Philip Edelbrock <phil@netroedge.com>
  * Copyright (C) 2003	Michiel Rook <michiel@grendelproject.nl>
  * Copyright (C) 2005	Grant Coady <gcoady.lk@gmail.com> with valuable
- * 				guidance from Jean Delvare
+ *				guidance from Jean Delvare
  *
  * Driver supports	Analog Devices		ADM9240
  *			Dallas Semiconductor	DS1780
@@ -204,7 +204,12 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[attr->index] = TEMP_TO_REG(val);
@@ -255,7 +260,12 @@ static ssize_t set_in_min(struct device *dev,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[attr->index] = IN_TO_REG(val, attr->index);
@@ -272,7 +282,12 @@ static ssize_t set_in_max(struct device *dev,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[attr->index] = IN_TO_REG(val, attr->index);
@@ -283,7 +298,7 @@ static ssize_t set_in_max(struct device *dev,
 }
 
 #define vin(nr)							\
-static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, 		\
+static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO,		\
 		show_in, NULL, nr);				\
 static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR,	\
 		show_in_min, set_in_min, nr);			\
@@ -357,9 +372,14 @@ static ssize_t set_fan_min(struct device *dev,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int nr = attr->index;
 	u8 new_div;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -465,7 +485,12 @@ static ssize_t set_aout(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm9240_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->aout = AOUT_TO_REG(val);
@@ -481,7 +506,12 @@ static ssize_t chassis_clear_legacy(struct device *dev,
 		const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	unsigned long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	dev_warn(dev, "Attribute chassis_clear is deprecated, "
 		 "use intrusion0_alarm instead\n");
@@ -632,7 +662,8 @@ static int adm9240_probe(struct i2c_client *new_client,
 	adm9240_init_client(new_client);
 
 	/* populate sysfs filesystem */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
@@ -681,8 +712,7 @@ static void adm9240_init_client(struct i2c_client *client)
 	} else { /* cold start: open limits before starting chip */
 		int i;
 
-		for (i = 0; i < 6; i++)
-		{
+		for (i = 0; i < 6; i++) {
 			i2c_smbus_write_byte_data(client,
 					ADM9240_REG_IN_MIN(i), 0);
 			i2c_smbus_write_byte_data(client,
@@ -717,8 +747,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
 	if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
 			|| !data->valid) {
 
-		for (i = 0; i < 6; i++) /* read voltages */
-		{
+		for (i = 0; i < 6; i++) { /* read voltages */
 			data->in[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN(i));
 		}
@@ -735,8 +764,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
 					i2c_smbus_read_byte_data(client,
 					ADM9240_REG_TEMP_CONF)) / 128;
 
-		for (i = 0; i < 2; i++) /* read fans */
-		{
+		for (i = 0; i < 2; i++) { /* read fans */
 			data->fan[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_FAN(i));
 
@@ -760,15 +788,13 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
 	if (time_after(jiffies, data->last_updated_config + (HZ * 300))
 			|| !data->valid) {
 
-		for (i = 0; i < 6; i++)
-		{
+		for (i = 0; i < 6; i++) {
 			data->in_min[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN_MIN(i));
 			data->in_max[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_IN_MAX(i));
 		}
-		for (i = 0; i < 2; i++)
-		{
+		for (i = 0; i < 2; i++) {
 			data->fan_min[i] = i2c_smbus_read_byte_data(client,
 					ADM9240_REG_FAN_MIN(i));
 		}
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 5b02f7a..ffe64f8 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -8,7 +8,7 @@
  *  published by the Free Software Foundation.
  *
  *  TODO: SPI, support for external temperature sensor
- * 	  use power-down mode for suspend?, interrupt handling?
+ *	  use power-down mode for suspend?, interrupt handling?
  */
 
 #include <linux/kernel.h>
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 7a14948..3df331a 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -65,68 +65,68 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
 #define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR	0x5F
 #define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR	0x60
 #define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR	0x63
-#define 	ADT7462_PWM_HYST_MASK		0x0F
-#define 	ADT7462_PWM_RANGE_MASK		0xF0
-#define		ADT7462_PWM_RANGE_SHIFT		4
+#define ADT7462_PWM_HYST_MASK			0x0F
+#define ADT7462_PWM_RANGE_MASK			0xF0
+#define	ADT7462_PWM_RANGE_SHIFT			4
 #define ADT7462_REG_PWM_CFG_BASE_ADDR		0x21
 #define ADT7462_REG_PWM_CFG_MAX_ADDR		0x24
-#define		ADT7462_PWM_CHANNEL_MASK	0xE0
-#define		ADT7462_PWM_CHANNEL_SHIFT	5
+#define	ADT7462_PWM_CHANNEL_MASK		0xE0
+#define	ADT7462_PWM_CHANNEL_SHIFT		5
 
 #define ADT7462_REG_PIN_CFG_BASE_ADDR		0x10
 #define ADT7462_REG_PIN_CFG_MAX_ADDR		0x13
-#define		ADT7462_PIN7_INPUT		0x01	/* cfg0 */
-#define		ADT7462_DIODE3_INPUT		0x20
-#define		ADT7462_DIODE1_INPUT		0x40
-#define		ADT7462_VID_INPUT		0x80
-#define		ADT7462_PIN22_INPUT		0x04	/* cfg1 */
-#define		ADT7462_PIN21_INPUT		0x08
-#define		ADT7462_PIN19_INPUT		0x10
-#define		ADT7462_PIN15_INPUT		0x20
-#define		ADT7462_PIN13_INPUT		0x40
-#define		ADT7462_PIN8_INPUT		0x80
-#define 	ADT7462_PIN23_MASK		0x03
-#define		ADT7462_PIN23_SHIFT		0
-#define		ADT7462_PIN26_MASK		0x0C	/* cfg2 */
-#define		ADT7462_PIN26_SHIFT		2
-#define		ADT7462_PIN25_MASK		0x30
-#define		ADT7462_PIN25_SHIFT		4
-#define		ADT7462_PIN24_MASK		0xC0
-#define		ADT7462_PIN24_SHIFT		6
-#define		ADT7462_PIN26_VOLT_INPUT	0x08
-#define		ADT7462_PIN25_VOLT_INPUT	0x20
-#define		ADT7462_PIN28_SHIFT		4	/* cfg3 */
-#define		ADT7462_PIN28_VOLT		0x5
+#define	ADT7462_PIN7_INPUT			0x01	/* cfg0 */
+#define	ADT7462_DIODE3_INPUT			0x20
+#define	ADT7462_DIODE1_INPUT			0x40
+#define	ADT7462_VID_INPUT			0x80
+#define	ADT7462_PIN22_INPUT			0x04	/* cfg1 */
+#define	ADT7462_PIN21_INPUT			0x08
+#define	ADT7462_PIN19_INPUT			0x10
+#define	ADT7462_PIN15_INPUT			0x20
+#define	ADT7462_PIN13_INPUT			0x40
+#define	ADT7462_PIN8_INPUT			0x80
+#define ADT7462_PIN23_MASK			0x03
+#define	ADT7462_PIN23_SHIFT			0
+#define	ADT7462_PIN26_MASK			0x0C	/* cfg2 */
+#define	ADT7462_PIN26_SHIFT			2
+#define	ADT7462_PIN25_MASK			0x30
+#define	ADT7462_PIN25_SHIFT			4
+#define	ADT7462_PIN24_MASK			0xC0
+#define	ADT7462_PIN24_SHIFT			6
+#define	ADT7462_PIN26_VOLT_INPUT		0x08
+#define	ADT7462_PIN25_VOLT_INPUT		0x20
+#define	ADT7462_PIN28_SHIFT			4	/* cfg3 */
+#define	ADT7462_PIN28_VOLT			0x5
 
 #define ADT7462_REG_ALARM1			0xB8
-#define 	ADT7462_LT_ALARM		0x02
-#define		ADT7462_R1T_ALARM		0x04
-#define		ADT7462_R2T_ALARM		0x08
-#define		ADT7462_R3T_ALARM		0x10
+#define ADT7462_LT_ALARM			0x02
+#define	ADT7462_R1T_ALARM			0x04
+#define	ADT7462_R2T_ALARM			0x08
+#define	ADT7462_R3T_ALARM			0x10
 #define ADT7462_REG_ALARM2			0xBB
-#define		ADT7462_V0_ALARM		0x01
-#define		ADT7462_V1_ALARM		0x02
-#define		ADT7462_V2_ALARM		0x04
-#define		ADT7462_V3_ALARM		0x08
-#define		ADT7462_V4_ALARM		0x10
-#define		ADT7462_V5_ALARM		0x20
-#define		ADT7462_V6_ALARM		0x40
-#define		ADT7462_V7_ALARM		0x80
+#define	ADT7462_V0_ALARM			0x01
+#define	ADT7462_V1_ALARM			0x02
+#define	ADT7462_V2_ALARM			0x04
+#define	ADT7462_V3_ALARM			0x08
+#define	ADT7462_V4_ALARM			0x10
+#define	ADT7462_V5_ALARM			0x20
+#define	ADT7462_V6_ALARM			0x40
+#define	ADT7462_V7_ALARM			0x80
 #define ADT7462_REG_ALARM3			0xBC
-#define		ADT7462_V8_ALARM		0x08
-#define		ADT7462_V9_ALARM		0x10
-#define		ADT7462_V10_ALARM		0x20
-#define		ADT7462_V11_ALARM		0x40
-#define		ADT7462_V12_ALARM		0x80
+#define	ADT7462_V8_ALARM			0x08
+#define	ADT7462_V9_ALARM			0x10
+#define	ADT7462_V10_ALARM			0x20
+#define	ADT7462_V11_ALARM			0x40
+#define	ADT7462_V12_ALARM			0x80
 #define ADT7462_REG_ALARM4			0xBD
-#define		ADT7462_F0_ALARM		0x01
-#define		ADT7462_F1_ALARM		0x02
-#define		ADT7462_F2_ALARM		0x04
-#define		ADT7462_F3_ALARM		0x08
-#define		ADT7462_F4_ALARM		0x10
-#define		ADT7462_F5_ALARM		0x20
-#define		ADT7462_F6_ALARM		0x40
-#define		ADT7462_F7_ALARM		0x80
+#define	ADT7462_F0_ALARM			0x01
+#define	ADT7462_F1_ALARM			0x02
+#define	ADT7462_F2_ALARM			0x04
+#define	ADT7462_F3_ALARM			0x08
+#define	ADT7462_F4_ALARM			0x10
+#define	ADT7462_F5_ALARM			0x20
+#define	ADT7462_F6_ALARM			0x40
+#define	ADT7462_F7_ALARM			0x80
 #define ADT7462_ALARM1				0x0000
 #define ADT7462_ALARM2				0x0100
 #define ADT7462_ALARM3				0x0200
@@ -136,8 +136,8 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
 
 #define ADT7462_TEMP_COUNT		4
 #define ADT7462_TEMP_REG(x)		(ADT7462_REG_TEMP_BASE_ADDR + (x * 2))
-#define ADT7462_TEMP_MIN_REG(x) 	(ADT7462_REG_MIN_TEMP_BASE_ADDR + (x))
-#define ADT7462_TEMP_MAX_REG(x) 	(ADT7462_REG_MAX_TEMP_BASE_ADDR + (x))
+#define ADT7462_TEMP_MIN_REG(x)		(ADT7462_REG_MIN_TEMP_BASE_ADDR + (x))
+#define ADT7462_TEMP_MAX_REG(x)		(ADT7462_REG_MAX_TEMP_BASE_ADDR + (x))
 #define TEMP_FRAC_OFFSET		6
 
 #define ADT7462_FAN_COUNT		8
@@ -1727,8 +1727,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
 static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
 		    show_pwm_auto_temp, set_pwm_auto_temp, 3);
 
-static struct attribute *adt7462_attr[] =
-{
+static struct attribute *adt7462_attr[] = {
 	&sensor_dev_attr_temp1_max.dev_attr.attr,
 	&sensor_dev_attr_temp2_max.dev_attr.attr,
 	&sensor_dev_attr_temp3_max.dev_attr.attr,
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 5e10c79..b23efd9 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -1131,8 +1131,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
 static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO,
 		    show_pwm_auto_temp, set_pwm_auto_temp, 3);
 
-static struct attribute *adt7470_attr[] =
-{
+static struct attribute *adt7470_attr[] = {
 	&dev_attr_alarm_mask.attr,
 	&dev_attr_num_temp_sensors.attr,
 	&dev_attr_auto_update_interval.attr,
@@ -1276,7 +1275,8 @@ static int adt7470_probe(struct i2c_client *client,
 
 	/* Register sysfs hooks */
 	data->attrs.attrs = adt7470_attr;
-	if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
+	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index 7dab354..71e9ac4 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -1232,7 +1232,7 @@ static void adt7475_remove_files(struct i2c_client *client,
 static int adt7475_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	static const char *names[] = {
+	static const char * const names[] = {
 		[adt7473] = "ADT7473",
 		[adt7475] = "ADT7475",
 		[adt7476] = "ADT7476",
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 89a6b9d..4a4bfef 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -47,7 +47,7 @@ static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
  * Insmod parameters
  */
 
-static int pwminv = 0;	/*Inverted PWM output. */
+static int pwminv;	/*Inverted PWM output. */
 module_param(pwminv, int, S_IRUGO);
 
 static int init = 1; /*Power-on initialization.*/
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index d7bd1f3..a5f1642 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -1,6 +1,6 @@
 /*
     asb100.c - Part of lm_sensors, Linux kernel modules for hardware
-	        monitoring
+		monitoring
 
     Copyright (C) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
 
@@ -103,8 +103,8 @@ static const u16 asb100_reg_temp_hyst[]	= {0, 0x3a, 0x153, 0x253, 0x19};
    Rounding and limit checking is only done on the TO_REG variants. */
 
 /* These constants are a guess, consistent w/ w83781d */
-#define ASB100_IN_MIN (   0)
-#define ASB100_IN_MAX (4080)
+#define ASB100_IN_MIN		0
+#define ASB100_IN_MAX		4080
 
 /* IN: 1/1000 V (0V to 4.08V)
    REG: 16mV/bit */
@@ -131,19 +131,19 @@ static u8 FAN_TO_REG(long rpm, int div)
 
 static int FAN_FROM_REG(u8 val, int div)
 {
-	return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
+	return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
 }
 
 /* These constants are a guess, consistent w/ w83781d */
-#define ASB100_TEMP_MIN (-128000)
-#define ASB100_TEMP_MAX ( 127000)
+#define ASB100_TEMP_MIN		-128000
+#define ASB100_TEMP_MAX		127000
 
 /* TEMP: 0.001C/bit (-128C to +127C)
    REG: 1C/bit, two's complement */
 static u8 TEMP_TO_REG(long temp)
 {
 	int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX);
-	ntemp += (ntemp<0 ? -500 : 500);
+	ntemp += (ntemp < 0 ? -500 : 500);
 	return (u8)(ntemp / 1000);
 }
 
@@ -171,7 +171,7 @@ static int ASB100_PWM_FROM_REG(u8 reg)
    REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
 static u8 DIV_TO_REG(long val)
 {
-	return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
+	return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1;
 }
 
 /* For each registered client, we need to keep some data in memory. That
@@ -253,8 +253,10 @@ static ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct asb100_data *data = i2c_get_clientdata(client); \
-	unsigned long val = simple_strtoul(buf, NULL, 10); \
- \
+	unsigned long val; \
+	int err = kstrtoul(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = IN_TO_REG(val); \
 	asb100_write_value(client, ASB100_REG_IN_##REG(nr), \
@@ -315,7 +317,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -335,8 +342,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
 	unsigned long min;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -421,8 +433,10 @@ static ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct asb100_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
+	long val; \
+	int err = kstrtol(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	switch (nr) { \
 	case 1: case 2: \
@@ -476,7 +490,13 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct asb100_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 
@@ -524,7 +544,12 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm &= 0x80; /* keep the enable bit */
@@ -546,7 +571,12 @@ static ssize_t set_pwm_enable1(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm &= 0x0f; /* keep the duty cycle bits */
@@ -768,7 +798,8 @@ static int asb100_probe(struct i2c_client *client,
 	data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2));
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &asb100_group)))
+	err = sysfs_create_group(&client->dev.kobj, &asb100_group);
+	if (err)
 		goto ERROR3;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 00e9851..4000fee 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -1318,7 +1318,8 @@ static int atk_probe_if(struct atk_data *data)
 	 */
 	if (new_if)
 		dev_info(dev, "Overriding interface detection\n");
-	if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle && !new_if)
+	if (data->rtmp_handle &&
+			data->rvlt_handle && data->rfan_handle && !new_if)
 		data->old_interface = true;
 	else if (data->enumerate_handle && data->read_handle &&
 			data->write_handle)
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 33cc143..d4a589b 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -1,6 +1,6 @@
 /*
     atxp1.c - kernel module for setting CPU VID and general purpose
-                     I/Os using the Attansic ATXP1 chip.
+		I/Os using the Attansic ATXP1 chip.
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -48,7 +48,7 @@ static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
 static int atxp1_probe(struct i2c_client *client,
 		       const struct i2c_device_id *id);
 static int atxp1_remove(struct i2c_client *client);
-static struct atxp1_data * atxp1_update_device(struct device *dev);
+static struct atxp1_data *atxp1_update_device(struct device *dev);
 static int atxp1_detect(struct i2c_client *client, struct i2c_board_info *info);
 
 static const struct i2c_device_id atxp1_id[] = {
@@ -83,7 +83,7 @@ struct atxp1_data {
 	u8 vrm;			/* Detected CPU VRM */
 };
 
-static struct atxp1_data * atxp1_update_device(struct device *dev)
+static struct atxp1_data *atxp1_update_device(struct device *dev)
 {
 	struct i2c_client *client;
 	struct atxp1_data *data;
@@ -97,7 +97,8 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
 
 		/* Update local register data */
 		data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID);
-		data->reg.cpu_vid = i2c_smbus_read_byte_data(client, ATXP1_CVID);
+		data->reg.cpu_vid = i2c_smbus_read_byte_data(client,
+							     ATXP1_CVID);
 		data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
 		data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
 
@@ -106,33 +107,41 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
 
 	mutex_unlock(&data->update_lock);
 
-	return(data);
+	return data;
 }
 
 /* sys file functions for cpu0_vid */
-static ssize_t atxp1_showvcore(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t atxp1_showvcore(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	int size;
 	struct atxp1_data *data;
 
 	data = atxp1_update_device(dev);
 
-	size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, data->vrm));
+	size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK,
+						 data->vrm));
 
 	return size;
 }
 
-static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t atxp1_storevcore(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
 {
 	struct atxp1_data *data;
 	struct i2c_client *client;
 	int vid, cvid;
-	unsigned int vcore;
+	unsigned long vcore;
+	int err;
 
 	client = to_i2c_client(dev);
 	data = atxp1_update_device(dev);
 
-	vcore = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &vcore);
+	if (err)
+		return err;
+
 	vcore /= 25;
 	vcore *= 25;
 
@@ -144,7 +153,10 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
 		return -1;
 	}
 
-	/* If output enabled, use control register value. Otherwise original CPU VID */
+	/*
+	 * If output enabled, use control register value.
+	 * Otherwise original CPU VID
+	 */
 	if (data->reg.vid & ATXP1_VIDENA)
 		cvid = data->reg.vid & ATXP1_VIDMASK;
 	else
@@ -154,18 +166,17 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
 	if (vid == cvid)
 		return count;
 
-	dev_dbg(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid);
+	dev_dbg(dev, "Setting VCore to %d mV (0x%02x)\n", (int)vcore, vid);
 
 	/* Write every 25 mV step to increase stability */
 	if (cvid > vid) {
-		for (; cvid >= vid; cvid--) {
-        		i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
-		}
-	}
-	else {
-		for (; cvid <= vid; cvid++) {
-        		i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
-		}
+		for (; cvid >= vid; cvid--)
+			i2c_smbus_write_byte_data(client,
+						ATXP1_VID, cvid | ATXP1_VIDENA);
+	} else {
+		for (; cvid <= vid; cvid++)
+			i2c_smbus_write_byte_data(client,
+						ATXP1_VID, cvid | ATXP1_VIDENA);
 	}
 
 	data->valid = 0;
@@ -176,10 +187,12 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
 /* CPU core reference voltage
     unit: millivolt
 */
-static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore,
+		   atxp1_storevcore);
 
 /* sys file functions for GPIO1 */
-static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t atxp1_showgpio1(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	int size;
 	struct atxp1_data *data;
@@ -191,21 +204,26 @@ static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr
 	return size;
 }
 
-static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *attr, const char*buf, size_t count)
+static ssize_t atxp1_storegpio1(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
 {
 	struct atxp1_data *data;
 	struct i2c_client *client;
-	unsigned int value;
+	unsigned long value;
+	int err;
 
 	client = to_i2c_client(dev);
 	data = atxp1_update_device(dev);
 
-	value = simple_strtoul(buf, NULL, 16);
+	err = kstrtoul(buf, 16, &value);
+	if (err)
+		return err;
 
 	value &= ATXP1_GPIO1MASK;
 
 	if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) {
-		dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+		dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
 
 		i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
 
@@ -221,7 +239,8 @@ static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *att
 static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1);
 
 /* sys file functions for GPIO2 */
-static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t atxp1_showgpio2(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	int size;
 	struct atxp1_data *data;
@@ -233,19 +252,22 @@ static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr
 	return size;
 }
 
-static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t atxp1_storegpio2(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
 {
-	struct atxp1_data *data;
-	struct i2c_client *client;
-	unsigned int value;
-
-	client = to_i2c_client(dev);
-	data = atxp1_update_device(dev);
+	struct atxp1_data *data = atxp1_update_device(dev);
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long value;
+	int err;
 
-	value = simple_strtoul(buf, NULL, 16) & 0xff;
+	err = kstrtoul(buf, 16, &value);
+	if (err)
+		return err;
+	value &= 0xff;
 
 	if (value != data->reg.gpio2) {
-		dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+		dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
 
 		i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
 
@@ -333,7 +355,8 @@ static int atxp1_probe(struct i2c_client *new_client,
 	mutex_init(&data->update_lock);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
@@ -357,7 +380,7 @@ exit:
 
 static int atxp1_remove(struct i2c_client *client)
 {
-	struct atxp1_data * data = i2c_get_clientdata(client);
+	struct atxp1_data *data = i2c_get_clientdata(client);
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &atxp1_group);
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index ffb229a..1f3113c 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -300,9 +300,8 @@ static int TEMP_RANGE_TO_REG(int val, int reg)
 	int i;
 
 	for (i = 15; i > 0; i--) {
-		if (val > (TEMP_RANGE[i] + TEMP_RANGE[i - 1] + 1) / 2) {
+		if (val > (TEMP_RANGE[i] + TEMP_RANGE[i - 1] + 1) / 2)
 			break;
-		}
 	}
 
 	return (reg & 0x0f) | (i << 4);
@@ -327,21 +326,19 @@ static inline int TEMP_HYST_TO_REG(int val, int ix, int reg)
 /* Fan input RPM */
 static inline int FAN_FROM_REG(int reg, int tpc)
 {
-	if (tpc) {
+	if (tpc)
 		return tpc * reg;
-	} else {
+	else
 		return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg;
-	}
 }
 
 static inline int FAN_TO_REG(int val, int tpc)
 {
-	if (tpc) {
+	if (tpc)
 		return SENSORS_LIMIT(val / tpc, 0, 0xffff);
-	} else {
+	else
 		return (val <= 0) ? 0xffff :
 			SENSORS_LIMIT(90000 * 60 / val, 0, 0xfffe);
-	}
 }
 
 /* Fan TPC (tach pulse count)
@@ -378,9 +375,8 @@ static int FAN_MAX_FROM_REG(int reg)
 	int i;
 
 	for (i = 10; i > 0; i--) {
-		if (reg == FAN_MAX[i]) {
+		if (reg == FAN_MAX[i])
 			break;
-		}
 	}
 
 	return 1000 + i * 500;
@@ -391,9 +387,8 @@ static int FAN_MAX_TO_REG(int val)
 	int i;
 
 	for (i = 10; i > 0; i--) {
-		if (val > (1000 + (i - 1) * 500)) {
+		if (val > (1000 + (i - 1) * 500))
 			break;
-		}
 	}
 
 	return FAN_MAX[i];
@@ -468,9 +463,8 @@ static int PWM_FREQ_TO_REG(int val, int reg)
 		i = 11;
 	} else {
 		for (i = 9; i > 0; i--) {
-			if (val > (PWM_FREQ[i] + PWM_FREQ[i - 1] + 1) / 2) {
+			if (val > (PWM_FREQ[i] + PWM_FREQ[i - 1] + 1) / 2)
 				break;
-			}
 		}
 	}
 
@@ -495,9 +489,8 @@ static int PWM_RR_TO_REG(int val, int ix, int reg)
 	int i;
 
 	for (i = 0; i < 7; i++) {
-		if (val > (PWM_RR[i] + PWM_RR[i + 1] + 1) / 2) {
+		if (val > (PWM_RR[i] + PWM_RR[i + 1] + 1) / 2)
 			break;
-		}
 	}
 
 	return (ix == 1) ? (reg & 0x8f) | (i << 4) : (reg & 0xf8) | i;
@@ -607,9 +600,8 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 			/* Voltage inputs are stored as 16 bit values even
 			 * though they have only 12 bits resolution. This is
 			 * to make it consistent with the temp inputs. */
-			if (ix == 7 && !(data->has_features & HAS_IN7)) {
+			if (ix == 7 && !(data->has_features & HAS_IN7))
 				continue;
-			}
 			data->in[ix] = dme1737_read(data,
 					DME1737_REG_IN(ix)) << 8;
 			data->in_min[ix] = dme1737_read(data,
@@ -642,16 +634,14 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 		 * which the registers are read (MSB first, then LSB) is
 		 * important! */
 		for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
-			if (ix == 5 && !(data->has_features & HAS_IN7)) {
+			if (ix == 5 && !(data->has_features & HAS_IN7))
 				continue;
-			}
 			lsb[ix] = dme1737_read(data,
 					DME1737_REG_IN_TEMP_LSB(ix));
 		}
 		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
-			if (ix == 7 && !(data->has_features & HAS_IN7)) {
+			if (ix == 7 && !(data->has_features & HAS_IN7))
 				continue;
-			}
 			data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] <<
 					DME1737_REG_IN_LSB_SHL[ix]) & 0xf0;
 		}
@@ -664,9 +654,8 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 		for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {
 			/* Skip reading registers if optional fans are not
 			 * present */
-			if (!(data->has_features & HAS_FAN(ix))) {
+			if (!(data->has_features & HAS_FAN(ix)))
 				continue;
-			}
 			data->fan[ix] = dme1737_read(data,
 					DME1737_REG_FAN(ix));
 			data->fan[ix] |= dme1737_read(data,
@@ -688,9 +677,8 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 		for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) {
 			/* Skip reading registers if optional PWMs are not
 			 * present */
-			if (!(data->has_features & HAS_PWM(ix))) {
+			if (!(data->has_features & HAS_PWM(ix)))
 				continue;
-			}
 			data->pwm[ix] = dme1737_read(data,
 					DME1737_REG_PWM(ix));
 			data->pwm_freq[ix] = dme1737_read(data,
@@ -711,9 +699,8 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 		/* Thermal zone registers */
 		for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {
 			/* Skip reading registers if zone3 is not present */
-			if ((ix == 2) && !(data->has_features & HAS_ZONE3)) {
+			if ((ix == 2) && !(data->has_features & HAS_ZONE3))
 				continue;
-			}
 			/* sch5127 zone2 registers are special */
 			if ((ix == 1) && (data->type == sch5127)) {
 				data->zone_low[1] = dme1737_read(data,
@@ -750,18 +737,12 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
 		 * Don't worry, an alarm will come back if the condition
 		 * that causes it still exists */
 		if (!data->client) {
-			if (data->alarms & 0xff0000) {
-				dme1737_write(data, DME1737_REG_ALARM3,
-					      0xff);
-			}
-			if (data->alarms & 0xff00) {
-				dme1737_write(data, DME1737_REG_ALARM2,
-					      0xff);
-			}
-			if (data->alarms & 0xff) {
-				dme1737_write(data, DME1737_REG_ALARM1,
-					      0xff);
-			}
+			if (data->alarms & 0xff0000)
+				dme1737_write(data, DME1737_REG_ALARM3, 0xff);
+			if (data->alarms & 0xff00)
+				dme1737_write(data, DME1737_REG_ALARM2, 0xff);
+			if (data->alarms & 0xff)
+				dme1737_write(data, DME1737_REG_ALARM1, 0xff);
 		}
 
 		data->last_update = jiffies;
@@ -822,7 +803,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
 		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -901,7 +887,12 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
 		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -952,11 +943,10 @@ static ssize_t show_zone(struct device *dev, struct device_attribute *attr,
 	switch (fn) {
 	case SYS_ZONE_AUTO_CHANNELS_TEMP:
 		/* check config2 for non-standard temp-to-zone mapping */
-		if ((ix == 1) && (data->config2 & 0x02)) {
+		if ((ix == 1) && (data->config2 & 0x02))
 			res = 4;
-		} else {
+		else
 			res = 1 << ix;
-		}
 		break;
 	case SYS_ZONE_AUTO_POINT1_TEMP_HYST:
 		res = TEMP_FROM_REG(data->zone_low[ix], 8) -
@@ -989,7 +979,12 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
 		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -1095,7 +1090,12 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -1170,21 +1170,19 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
 
 	switch (fn) {
 	case SYS_PWM:
-		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 0) {
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 0)
 			res = 255;
-		} else {
+		else
 			res = data->pwm[ix];
-		}
 		break;
 	case SYS_PWM_FREQ:
 		res = PWM_FREQ_FROM_REG(data->pwm_freq[ix]);
 		break;
 	case SYS_PWM_ENABLE:
-		if (ix >= 3) {
+		if (ix >= 3)
 			res = 1; /* pwm[5-6] hard-wired to manual mode */
-		} else {
+		else
 			res = PWM_EN_FROM_REG(data->pwm_config[ix]);
-		}
 		break;
 	case SYS_PWM_RAMP_RATE:
 		/* Only valid for pwm[1-3] */
@@ -1192,19 +1190,17 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
 		break;
 	case SYS_PWM_AUTO_CHANNELS_ZONE:
 		/* Only valid for pwm[1-3] */
-		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2)
 			res = PWM_ACZ_FROM_REG(data->pwm_config[ix]);
-		} else {
+		else
 			res = data->pwm_acz[ix];
-		}
 		break;
 	case SYS_PWM_AUTO_PWM_MIN:
 		/* Only valid for pwm[1-3] */
-		if (PWM_OFF_FROM_REG(data->pwm_rr[0], ix)) {
+		if (PWM_OFF_FROM_REG(data->pwm_rr[0], ix))
 			res = data->pwm_min[ix];
-		} else {
+		else
 			res = 0;
-		}
 		break;
 	case SYS_PWM_AUTO_POINT1_PWM:
 		/* Only valid for pwm[1-3] */
@@ -1233,7 +1229,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -1426,7 +1427,12 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
 	struct dme1737_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	data->vrm = val;
 	return count;
@@ -1975,9 +1981,8 @@ static void dme1737_chmod_group(struct device *dev,
 {
 	struct attribute **attr;
 
-	for (attr = group->attrs; *attr; attr++) {
+	for (attr = group->attrs; *attr; attr++)
 		dme1737_chmod_file(dev, *attr, mode);
-	}
 }
 
 static void dme1737_remove_files(struct device *dev)
@@ -2003,26 +2008,20 @@ static void dme1737_remove_files(struct device *dev)
 		}
 	}
 
-	if (data->has_features & HAS_TEMP_OFFSET) {
+	if (data->has_features & HAS_TEMP_OFFSET)
 		sysfs_remove_group(&dev->kobj, &dme1737_temp_offset_group);
-	}
-	if (data->has_features & HAS_VID) {
+	if (data->has_features & HAS_VID)
 		sysfs_remove_group(&dev->kobj, &dme1737_vid_group);
-	}
-	if (data->has_features & HAS_ZONE3) {
+	if (data->has_features & HAS_ZONE3)
 		sysfs_remove_group(&dev->kobj, &dme1737_zone3_group);
-	}
-	if (data->has_features & HAS_ZONE_HYST) {
+	if (data->has_features & HAS_ZONE_HYST)
 		sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group);
-	}
-	if (data->has_features & HAS_IN7) {
+	if (data->has_features & HAS_IN7)
 		sysfs_remove_group(&dev->kobj, &dme1737_in7_group);
-	}
 	sysfs_remove_group(&dev->kobj, &dme1737_group);
 
-	if (!data->client) {
+	if (!data->client)
 		sysfs_remove_file(&dev->kobj, &dev_attr_name.attr);
-	}
 }
 
 static int dme1737_create_files(struct device *dev)
@@ -2033,48 +2032,41 @@ static int dme1737_create_files(struct device *dev)
 	/* Create a name attribute for ISA devices */
 	if (!data->client) {
 		err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr);
-		if (err) {
+		if (err)
 			goto exit;
-		}
 	}
 
 	/* Create standard sysfs attributes */
 	err = sysfs_create_group(&dev->kobj, &dme1737_group);
-	if (err) {
+	if (err)
 		goto exit_remove;
-	}
 
 	/* Create chip-dependent sysfs attributes */
 	if (data->has_features & HAS_TEMP_OFFSET) {
 		err = sysfs_create_group(&dev->kobj,
 					 &dme1737_temp_offset_group);
-		if (err) {
+		if (err)
 			goto exit_remove;
-		}
 	}
 	if (data->has_features & HAS_VID) {
 		err = sysfs_create_group(&dev->kobj, &dme1737_vid_group);
-		if (err) {
+		if (err)
 			goto exit_remove;
-		}
 	}
 	if (data->has_features & HAS_ZONE3) {
 		err = sysfs_create_group(&dev->kobj, &dme1737_zone3_group);
-		if (err) {
+		if (err)
 			goto exit_remove;
-		}
 	}
 	if (data->has_features & HAS_ZONE_HYST) {
 		err = sysfs_create_group(&dev->kobj, &dme1737_zone_hyst_group);
-		if (err) {
+		if (err)
 			goto exit_remove;
-		}
 	}
 	if (data->has_features & HAS_IN7) {
 		err = sysfs_create_group(&dev->kobj, &dme1737_in7_group);
-		if (err) {
+		if (err)
 			goto exit_remove;
-		}
 	}
 
 	/* Create fan sysfs attributes */
@@ -2082,9 +2074,8 @@ static int dme1737_create_files(struct device *dev)
 		if (data->has_features & HAS_FAN(ix)) {
 			err = sysfs_create_group(&dev->kobj,
 						 &dme1737_fan_group[ix]);
-			if (err) {
+			if (err)
 				goto exit_remove;
-			}
 		}
 	}
 
@@ -2093,15 +2084,13 @@ static int dme1737_create_files(struct device *dev)
 		if (data->has_features & HAS_PWM(ix)) {
 			err = sysfs_create_group(&dev->kobj,
 						 &dme1737_pwm_group[ix]);
-			if (err) {
+			if (err)
 				goto exit_remove;
-			}
 			if ((data->has_features & HAS_PWM_MIN) && (ix < 3)) {
 				err = sysfs_create_file(&dev->kobj,
 						dme1737_auto_pwm_min_attr[ix]);
-				if (err) {
+				if (err)
 					goto exit_remove;
-				}
 			}
 		}
 	}
@@ -2199,16 +2188,14 @@ static int dme1737_init_device(struct device *dev)
 	if (client) {   /* I2C chip */
 		data->config2 = dme1737_read(data, DME1737_REG_CONFIG2);
 		/* Check if optional fan3 input is enabled */
-		if (data->config2 & 0x04) {
+		if (data->config2 & 0x04)
 			data->has_features |= HAS_FAN(2);
-		}
 
 		/* Fan4 and pwm3 are only available if the client's I2C address
 		 * is the default 0x2e. Otherwise the I/Os associated with
 		 * these functions are used for addr enable/select. */
-		if (client->addr == 0x2e) {
+		if (client->addr == 0x2e)
 			data->has_features |= HAS_FAN(3) | HAS_PWM(2);
-		}
 
 		/* Determine which of the optional fan[5-6] and pwm[5-6]
 		 * features are enabled. For this, we need to query the runtime
@@ -2298,9 +2285,8 @@ static int dme1737_init_device(struct device *dev)
 	data->pwm_acz[2] = 4;	/* pwm3 -> zone3 */
 
 	/* Set VRM */
-	if (data->has_features & HAS_VID) {
+	if (data->has_features & HAS_VID)
 		data->vrm = vid_which_vrm();
-	}
 
 	return 0;
 }
@@ -2341,18 +2327,14 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data)
 	/* Read the runtime registers to determine which optional features
 	 * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set
 	 * to '10' if the respective feature is enabled. */
-	if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */
+	if ((inb(addr + 0x43) & 0x0c) == 0x08) /* fan6 */
 		data->has_features |= HAS_FAN(5);
-	}
-	if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */
+	if ((inb(addr + 0x44) & 0x0c) == 0x08) /* pwm6 */
 		data->has_features |= HAS_PWM(5);
-	}
-	if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */
+	if ((inb(addr + 0x45) & 0x0c) == 0x08) /* fan5 */
 		data->has_features |= HAS_FAN(4);
-	}
-	if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */
+	if ((inb(addr + 0x46) & 0x0c) == 0x08) /* pwm5 */
 		data->has_features |= HAS_PWM(4);
-	}
 
 exit:
 	dme1737_sio_exit(sio_cip);
@@ -2369,9 +2351,8 @@ static int dme1737_i2c_detect(struct i2c_client *client,
 	u8 company, verstep = 0;
 	const char *name;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
-	}
 
 	company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
 	verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
@@ -2610,11 +2591,10 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (data->type == sch5127) {
+	if (data->type == sch5127)
 		data->name = "sch5127";
-	} else {
+	else
 		data->name = "sch311x";
-	}
 
 	/* Initialize the mutex */
 	mutex_init(&data->update_lock);
@@ -2689,9 +2669,8 @@ static int __init dme1737_init(void)
 	unsigned short addr;
 
 	err = i2c_add_driver(&dme1737_i2c_driver);
-	if (err) {
+	if (err)
 		goto exit;
-	}
 
 	if (dme1737_isa_detect(0x2e, &addr) &&
 	    dme1737_isa_detect(0x4e, &addr) &&
@@ -2703,15 +2682,13 @@ static int __init dme1737_init(void)
 	}
 
 	err = platform_driver_register(&dme1737_isa_driver);
-	if (err) {
+	if (err)
 		goto exit_del_i2c_driver;
-	}
 
 	/* Sets global pdev as a side effect */
 	err = dme1737_isa_device_add(addr);
-	if (err) {
+	if (err)
 		goto exit_del_isa_driver;
-	}
 
 	return 0;
 
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index ef1ac996..e23a8ab 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -1,9 +1,9 @@
 /*
     ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
+		monitoring
     Christian W. Zuckschwerdt  <zany@triq.net>  2000-11-23
     based on lm75.c by Frodo Looijaard <frodol@dds.nl>
-    Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 
+    Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
     the help of Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
@@ -67,7 +67,7 @@ static const u8 DS1621_REG_TEMP[3] = {
 
 /* Conversions */
 #define ALARMS_FROM_REG(val) ((val) & \
-                              (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
+			(DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
 
 /* Each client has this additional data */
 struct ds1621_data {
@@ -93,10 +93,10 @@ static void ds1621_init_client(struct i2c_client *client)
 		new_conf &= ~DS1621_REG_CONFIG_POLARITY;
 	else if (polarity == 1)
 		new_conf |= DS1621_REG_CONFIG_POLARITY;
-	
+
 	if (conf != new_conf)
 		i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf);
-	
+
 	/* start conversion */
 	i2c_smbus_write_byte(client, DS1621_COM_START);
 }
@@ -155,10 +155,15 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct ds1621_data *data = i2c_get_clientdata(client);
-	u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10));
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	data->temp[attr->index] = val;
+	data->temp[attr->index] = LM75_TEMP_TO_REG(val);
 	i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index],
 				     data->temp[attr->index]);
 	mutex_unlock(&data->update_lock);
@@ -212,8 +217,8 @@ static int ds1621_detect(struct i2c_client *client,
 	int conf, temp;
 	int i;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 
-				     | I2C_FUNC_SMBUS_WORD_DATA 
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+				     | I2C_FUNC_SMBUS_WORD_DATA
 				     | I2C_FUNC_SMBUS_WRITE_BYTE))
 		return -ENODEV;
 
@@ -254,7 +259,8 @@ static int ds1621_probe(struct i2c_client *client,
 	ds1621_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
+	err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
@@ -265,11 +271,11 @@ static int ds1621_probe(struct i2c_client *client,
 
 	return 0;
 
-      exit_remove_files:
+exit_remove_files:
 	sysfs_remove_group(&client->dev.kobj, &ds1621_group);
-      exit_free:
+exit_free:
 	kfree(data);
-      exit:
+exit:
 	return err;
 }
 
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 92f9497..859b203 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -202,7 +202,7 @@ struct f71805f_sio_data {
 
 static inline long in_from_reg(u8 reg)
 {
-	return (reg * 8);
+	return reg * 8;
 }
 
 /* The 2 least significant bits are not used */
@@ -212,13 +212,13 @@ static inline u8 in_to_reg(long val)
 		return 0;
 	if (val >= 2016)
 		return 0xfc;
-	return (((val + 16) / 32) << 2);
+	return ((val + 16) / 32) << 2;
 }
 
 /* in0 is downscaled by a factor 2 internally */
 static inline long in0_from_reg(u8 reg)
 {
-	return (reg * 16);
+	return reg * 16;
 }
 
 static inline u8 in0_to_reg(long val)
@@ -227,7 +227,7 @@ static inline u8 in0_to_reg(long val)
 		return 0;
 	if (val >= 4032)
 		return 0xfc;
-	return (((val + 32) / 64) << 2);
+	return ((val + 32) / 64) << 2;
 }
 
 /* The 4 most significant bits are not used */
@@ -236,7 +236,7 @@ static inline long fan_from_reg(u16 reg)
 	reg &= 0xfff;
 	if (!reg || reg == 0xfff)
 		return 0;
-	return (1500000 / reg);
+	return 1500000 / reg;
 }
 
 static inline u16 fan_to_reg(long rpm)
@@ -246,7 +246,7 @@ static inline u16 fan_to_reg(long rpm)
 	   so that no alarm will ever trigger. */
 	if (rpm < 367)
 		return 0xfff;
-	return (1500000 / rpm);
+	return 1500000 / rpm;
 }
 
 static inline unsigned long pwm_freq_from_reg(u8 reg)
@@ -278,7 +278,7 @@ static inline int pwm_mode_from_reg(u8 reg)
 
 static inline long temp_from_reg(u8 reg)
 {
-	return (reg * 1000);
+	return reg * 1000;
 }
 
 static inline u8 temp_to_reg(long val)
@@ -287,7 +287,7 @@ static inline u8 temp_to_reg(long val)
 		val = 0;
 	else if (val > 1000 * 0xff)
 		val = 0xff;
-	return ((val + 500) / 1000);
+	return (val + 500) / 1000;
 }
 
 /*
@@ -455,7 +455,12 @@ static ssize_t set_in0_max(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_high[nr] = in0_to_reg(val);
@@ -471,7 +476,12 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_low[nr] = in0_to_reg(val);
@@ -517,7 +527,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_high[nr] = in_to_reg(val);
@@ -533,7 +548,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_low[nr] = in_to_reg(val);
@@ -579,7 +599,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_low[nr] = fan_to_reg(val);
@@ -595,7 +620,12 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_target[nr] = fan_to_reg(val);
@@ -664,7 +694,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (val > 255)
 		return -EINVAL;
@@ -685,8 +720,13 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	u8 reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (val < 1 || val > 3)
 		return -EINVAL;
@@ -730,7 +770,12 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm_freq[nr] = pwm_freq_to_reg(val);
@@ -742,7 +787,7 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
 
 static ssize_t show_pwm_auto_point_temp(struct device *dev,
 					struct device_attribute *devattr,
-					char* buf)
+					char *buf)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
@@ -755,13 +800,18 @@ static ssize_t show_pwm_auto_point_temp(struct device *dev,
 
 static ssize_t set_pwm_auto_point_temp(struct device *dev,
 				       struct device_attribute *devattr,
-				       const char* buf, size_t count)
+				       const char *buf, size_t count)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	int pwmnr = attr->nr;
 	int apnr = attr->index;
-	unsigned long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val);
@@ -774,7 +824,7 @@ static ssize_t set_pwm_auto_point_temp(struct device *dev,
 
 static ssize_t show_pwm_auto_point_fan(struct device *dev,
 				       struct device_attribute *devattr,
-				       char* buf)
+				       char *buf)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
@@ -787,18 +837,23 @@ static ssize_t show_pwm_auto_point_fan(struct device *dev,
 
 static ssize_t set_pwm_auto_point_fan(struct device *dev,
 				      struct device_attribute *devattr,
-				      const char* buf, size_t count)
+				      const char *buf, size_t count)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	int pwmnr = attr->nr;
 	int apnr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val);
 	f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr),
-		        data->auto_points[pwmnr].fan[apnr]);
+			data->auto_points[pwmnr].fan[apnr]);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -851,7 +906,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_high[nr] = temp_to_reg(val);
@@ -867,7 +927,12 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
 	struct f71805f_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst[nr] = temp_to_reg(val);
@@ -920,9 +985,9 @@ static ssize_t show_name(struct device *dev, struct device_attribute
 }
 
 static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
-static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
+static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR,
 			  show_in0_max, set_in0_max, 0);
-static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR,
+static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR,
 			  show_in0_min, set_in0_min, 0);
 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
 static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR,
@@ -1304,12 +1369,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
 	struct resource *res;
 	int i, err;
 
-	static const char *names[] = {
+	static const char * const names[] = {
 		"f71805f",
 		"f71872f",
 	};
 
-	if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		pr_err("Out of memory\n");
 		goto exit;
@@ -1347,40 +1413,47 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
 	f71805f_init_device(data);
 
 	/* Register sysfs interface files */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
+	err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group);
+	if (err)
 		goto exit_release_region;
 	if (data->has_in & (1 << 4)) { /* in4 */
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &f71805f_group_optin[0])))
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &f71805f_group_optin[0]);
+		if (err)
 			goto exit_remove_files;
 	}
 	if (data->has_in & (1 << 8)) { /* in8 */
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &f71805f_group_optin[1])))
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &f71805f_group_optin[1]);
+		if (err)
 			goto exit_remove_files;
 	}
 	if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &f71805f_group_optin[2])))
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &f71805f_group_optin[2]);
+		if (err)
 			goto exit_remove_files;
 	}
 	if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &f71805f_group_optin[3])))
+		err = sysfs_create_group(&pdev->dev.kobj,
+					 &f71805f_group_optin[3]);
+		if (err)
 			goto exit_remove_files;
 	}
 	for (i = 0; i < 3; i++) {
 		/* If control mode is PWM, create pwm_freq file */
 		if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {
-			if ((err = sysfs_create_file(&pdev->dev.kobj,
-					f71805f_attributes_pwm_freq[i])))
+			err = sysfs_create_file(&pdev->dev.kobj,
+						f71805f_attributes_pwm_freq[i]);
+			if (err)
 				goto exit_remove_files;
 		}
 		/* If PWM is in manual mode, add write permission */
 		if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {
-			if ((err = sysfs_chmod_file(&pdev->dev.kobj,
-						    f71805f_attr_pwm[i],
-						    S_IRUGO | S_IWUSR))) {
+			err = sysfs_chmod_file(&pdev->dev.kobj,
+					       f71805f_attr_pwm[i],
+					       S_IRUGO | S_IWUSR);
+			if (err) {
 				dev_err(&pdev->dev, "chmod +w pwm%d failed\n",
 					i + 1);
 				goto exit_remove_files;
@@ -1495,7 +1568,7 @@ static int __init f71805f_find(int sioaddr, unsigned short *address,
 	int err = -ENODEV;
 	u16 devid;
 
-	static const char *names[] = {
+	static const char * const names[] = {
 		"F71805F/FG",
 		"F71872F/FG or F71806F/FG",
 	};
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index e503058..2cada92 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -112,7 +112,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
 enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
 	     f71889fg, f71889ed, f71889a, f8000, f81865f };
 
-static const char *f71882fg_names[] = {
+static const char *const f71882fg_names[] = {
 	"f71808e",
 	"f71808a",
 	"f71858fg",
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index aa6d8b6..06cbf77 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -76,12 +76,12 @@ enum chips { fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl };
 #define FSCHMD_CONTROL_ALERT_LED	0x01
 
 /* watchdog */
-static const u8 FSCHMD_REG_WDOG_CONTROL[7] =
-	{ 0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 };
-static const u8 FSCHMD_REG_WDOG_STATE[7] =
-	{ 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 };
-static const u8 FSCHMD_REG_WDOG_PRESET[7] =
-	{ 0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a };
+static const u8 FSCHMD_REG_WDOG_CONTROL[7] = {
+	0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 };
+static const u8 FSCHMD_REG_WDOG_STATE[7] = {
+	0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 };
+static const u8 FSCHMD_REG_WDOG_PRESET[7] = {
+	0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a };
 
 #define FSCHMD_WDOG_CONTROL_TRIGGER	0x10
 #define FSCHMD_WDOG_CONTROL_STARTED	0x10 /* the same as trigger */
@@ -359,9 +359,14 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
 {
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct fschmd_data *data = dev_get_drvdata(dev);
-	long v = simple_strtol(buf, NULL, 10) / 1000;
+	long v;
+	int err;
 
-	v = SENSORS_LIMIT(v, -128, 127) + 128;
+	err = kstrtol(buf, 10, &v);
+	if (err)
+		return err;
+
+	v = SENSORS_LIMIT(v / 1000, -128, 127) + 128;
 
 	mutex_lock(&data->update_lock);
 	i2c_smbus_write_byte_data(to_i2c_client(dev),
@@ -427,12 +432,23 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct fschmd_data *data = dev_get_drvdata(dev);
 	/* supported values: 2, 4, 8 */
-	unsigned long v = simple_strtoul(buf, NULL, 10);
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
 
 	switch (v) {
-	case 2: v = 1; break;
-	case 4: v = 2; break;
-	case 8: v = 3; break;
+	case 2:
+		v = 1;
+		break;
+	case 4:
+		v = 2;
+		break;
+	case 8:
+		v = 3;
+		break;
 	default:
 		dev_err(dev, "fan_div value %lu not supported. "
 			"Choose one of 2, 4 or 8!\n", v);
@@ -502,7 +518,12 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
 {
 	int index = to_sensor_dev_attr(devattr)->index;
 	struct fschmd_data *data = dev_get_drvdata(dev);
-	unsigned long v = simple_strtoul(buf, NULL, 10);
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
 
 	/* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
 	if (v || data->kind == fscsyl) {
@@ -540,7 +561,12 @@ static ssize_t store_alert_led(struct device *dev,
 {
 	u8 reg;
 	struct fschmd_data *data = dev_get_drvdata(dev);
-	unsigned long v = simple_strtoul(buf, NULL, 10);
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -847,7 +873,8 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf,
 	return count;
 }
 
-static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+static long watchdog_ioctl(struct file *filp, unsigned int cmd,
+			   unsigned long arg)
 {
 	struct watchdog_info ident = {
 		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 781277d..81b6e35 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -1,11 +1,11 @@
 /*
     g760a - Driver for the Global Mixed-mode Technology Inc. G760A
-            fan speed PWM controller chip
+	    fan speed PWM controller chip
 
     Copyright (C) 2007  Herbert Valerio Riedel <hvr@gnu.org>
 
     Complete datasheet is available at GMT's website:
-      http://www.gmt.com.tw/product/datasheet/EDS-760A.pdf 
+      http://www.gmt.com.tw/product/datasheet/EDS-760A.pdf
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c
index a13e2da..8d0f71d 100644
--- a/drivers/hwmon/gl518sm.c
+++ b/drivers/hwmon/gl518sm.c
@@ -83,11 +83,12 @@ enum chips { gl518sm_r00, gl518sm_r80 };
 
 #define RAW_FROM_REG(val)	val
 
-#define BOOL_FROM_REG(val)	((val)?0:1)
-#define BOOL_TO_REG(val)	((val)?0:1)
+#define BOOL_FROM_REG(val)	((val) ? 0 : 1)
+#define BOOL_TO_REG(val)	((val) ? 0 : 1)
 
-#define TEMP_TO_REG(val)	(SENSORS_LIMIT(((((val)<0? \
-				(val)-500:(val)+500)/1000)+119),0,255))
+#define TEMP_TO_REG(val)	SENSORS_LIMIT(((((val) < 0 ? \
+				(val) - 500 : \
+				(val) + 500) / 1000) + 119), 0, 255)
 #define TEMP_FROM_REG(val)	(((val) - 119) * 1000)
 
 static inline u8 FAN_TO_REG(long rpm, int div)
@@ -98,13 +99,13 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 	rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div;
 	return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255);
 }
-#define FAN_FROM_REG(val,div)	((val)==0 ? 0 : (480000/((val)*(div))))
+#define FAN_FROM_REG(val, div)	((val) == 0 ? 0 : (480000 / ((val) * (div))))
 
-#define IN_TO_REG(val)		(SENSORS_LIMIT((((val)+9)/19),0,255))
-#define IN_FROM_REG(val)	((val)*19)
+#define IN_TO_REG(val)		SENSORS_LIMIT((((val) + 9) / 19), 0, 255)
+#define IN_FROM_REG(val)	((val) * 19)
 
-#define VDD_TO_REG(val)		(SENSORS_LIMIT((((val)*4+47)/95),0,255))
-#define VDD_FROM_REG(val)	(((val)*95+2)/4)
+#define VDD_TO_REG(val)		SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255)
+#define VDD_FROM_REG(val)	(((val) * 95 + 2) / 4)
 
 #define DIV_FROM_REG(val)	(1 << (val))
 
@@ -169,7 +170,8 @@ static struct i2c_driver gl518_driver = {
  */
 
 #define show(type, suffix, value)					\
-static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf)		\
+static ssize_t show_##suffix(struct device *dev,			\
+			     struct device_attribute *attr, char *buf)	\
 {									\
 	struct gl518_data *data = gl518_update_device(dev);		\
 	return sprintf(buf, "%d\n", type##_FROM_REG(data->value));	\
@@ -222,12 +224,16 @@ static ssize_t show_fan_div(struct device *dev,
 }
 
 #define set(type, suffix, value, reg)					\
-static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
-	size_t count)							\
+static ssize_t set_##suffix(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t count)		\
 {									\
 	struct i2c_client *client = to_i2c_client(dev);			\
 	struct gl518_data *data = i2c_get_clientdata(client);		\
-	long val = simple_strtol(buf, NULL, 10);			\
+	long val;							\
+	int err = kstrtol(buf, 10, &val);				\
+	if (err)							\
+		return err;						\
 									\
 	mutex_lock(&data->update_lock);					\
 	data->value = type##_TO_REG(val);				\
@@ -237,13 +243,17 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c
 }
 
 #define set_bits(type, suffix, value, reg, mask, shift)			\
-static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
-	size_t count)							\
+static ssize_t set_##suffix(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    const char *buf, size_t count)		\
 {									\
 	struct i2c_client *client = to_i2c_client(dev);			\
 	struct gl518_data *data = i2c_get_clientdata(client);		\
 	int regvalue;							\
-	unsigned long val = simple_strtoul(buf, NULL, 10);		\
+	unsigned long val;						\
+	int err = kstrtoul(buf, 10, &val);				\
+	if (err)							\
+		return err;						\
 									\
 	mutex_lock(&data->update_lock);					\
 	regvalue = gl518_read_value(client, reg);			\
@@ -280,7 +290,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	struct gl518_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT);
@@ -308,13 +323,26 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	struct gl518_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	int regvalue;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	switch (val) {
-	case 1: val = 0; break;
-	case 2: val = 1; break;
-	case 4: val = 2; break;
-	case 8: val = 3; break;
+	case 1:
+		val = 0;
+		break;
+	case 2:
+		val = 1;
+		break;
+	case 4:
+		val = 2;
+		break;
+	case 8:
+		val = 3;
+		break;
 	default:
 		dev_err(dev, "Invalid fan clock divider %lu, choose one "
 			"of 1, 2, 4 or 8\n", val);
@@ -395,8 +423,12 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
 	struct gl518_data *data = i2c_get_clientdata(client);
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	unsigned long bit;
+	int err;
+
+	err = kstrtoul(buf, 10, &bit);
+	if (err)
+		return err;
 
-	bit = simple_strtoul(buf, NULL, 10);
 	if (bit & ~1)
 		return -EINVAL;
 
@@ -528,12 +560,14 @@ static int gl518_probe(struct i2c_client *client,
 	gl518_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
+	err = sysfs_create_group(&client->dev.kobj, &gl518_group);
+	if (err)
 		goto exit_free;
-	if (data->type == gl518sm_r80)
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					      &gl518_group_r80)))
+	if (data->type == gl518sm_r80) {
+		err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80);
+		if (err)
 			goto exit_remove_files;
+	}
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c
index cd6085b..1909097 100644
--- a/drivers/hwmon/gl520sm.c
+++ b/drivers/hwmon/gl520sm.c
@@ -1,9 +1,9 @@
 /*
     gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
+		monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
-                              Kyösti Mälkki <kmalkki@cc.hut.fi>
-    Copyright (c) 2005        Maarten Deprez <maartendeprez@users.sourceforge.net>
+			      Kyösti Mälkki <kmalkki@cc.hut.fi>
+    Copyright (c) 2005	Maarten Deprez <maartendeprez@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
@@ -142,11 +142,11 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL);
 
-#define VDD_FROM_REG(val) (((val)*95+2)/4)
-#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
+#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4)
+#define VDD_TO_REG(val) SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255)
 
-#define IN_FROM_REG(val) ((val)*19)
-#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
+#define IN_FROM_REG(val) ((val) * 19)
+#define IN_TO_REG(val) SENSORS_LIMIT((((val) + 9) / 19), 0, 255)
 
 static ssize_t get_in_input(struct device *dev, struct device_attribute *attr,
 			    char *buf)
@@ -193,8 +193,13 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	long v = simple_strtol(buf, NULL, 10);
 	u8 r;
+	long v;
+	int err;
+
+	err = kstrtol(buf, 10, &v);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -222,8 +227,13 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	long v = simple_strtol(buf, NULL, 10);
 	u8 r;
+	long v;
+	int err;
+
+	err = kstrtol(buf, 10, &v);
+	if (err)
+		return err;
 
 	if (n == 0)
 		r = VDD_TO_REG(v);
@@ -272,8 +282,10 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR,
 		get_in_max, set_in_max, 4);
 
 #define DIV_FROM_REG(val) (1 << (val))
-#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
-#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255))
+#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div))))
+#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \
+	SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, \
+		      255))
 
 static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr,
 			     char *buf)
@@ -317,8 +329,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	unsigned long v = simple_strtoul(buf, NULL, 10);
 	u8 r;
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	r = FAN_TO_REG(v, data->fan_div[n]);
@@ -351,16 +368,30 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	unsigned long v = simple_strtoul(buf, NULL, 10);
 	u8 r;
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
 
 	switch (v) {
-	case 1: r = 0; break;
-	case 2: r = 1; break;
-	case 4: r = 2; break;
-	case 8: r = 3; break;
+	case 1:
+		r = 0;
+		break;
+	case 2:
+		r = 1;
+		break;
+	case 4:
+		r = 2;
+		break;
+	case 8:
+		r = 3;
+		break;
 	default:
-		dev_err(&client->dev, "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
+		dev_err(&client->dev,
+	"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
 		return -EINVAL;
 	}
 
@@ -385,7 +416,15 @@ static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
-	u8 r = simple_strtoul(buf, NULL, 10)?1:0;
+	u8 r;
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
+
+	r = (v ? 1 : 0);
 
 	mutex_lock(&data->update_lock);
 	data->fan_off = r;
@@ -410,7 +449,8 @@ static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR,
 		get_fan_off, set_fan_off);
 
 #define TEMP_FROM_REG(val) (((val) - 130) * 1000)
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255))
+#define TEMP_TO_REG(val) SENSORS_LIMIT(((((val) < 0 ? \
+			(val) - 500 : (val) + 500) / 1000) + 130), 0, 255)
 
 static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr,
 			      char *buf)
@@ -430,8 +470,8 @@ static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr,
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n]));
 }
 
-static ssize_t get_temp_max_hyst(struct device *dev, struct device_attribute
-				 *attr, char *buf)
+static ssize_t get_temp_max_hyst(struct device *dev,
+				 struct device_attribute *attr, char *buf)
 {
 	int n = to_sensor_dev_attr(attr)->index;
 	struct gl520_data *data = gl520_update_device(dev);
@@ -445,7 +485,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	long v = simple_strtol(buf, NULL, 10);
+	long v;
+	int err;
+
+	err = kstrtol(buf, 10, &v);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[n] = TEMP_TO_REG(v);
@@ -460,7 +505,12 @@ static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
 	int n = to_sensor_dev_attr(attr)->index;
-	long v = simple_strtol(buf, NULL, 10);
+	long v;
+	int err;
+
+	err = kstrtol(buf, 10, &v);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max_hyst[n] = TEMP_TO_REG(v);
@@ -507,7 +557,15 @@ static ssize_t set_beep_enable(struct device *dev, struct device_attribute
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
-	u8 r = simple_strtoul(buf, NULL, 10)?0:1;
+	u8 r;
+	unsigned long v;
+	int err;
+
+	err = kstrtoul(buf, 10, &v);
+	if (err)
+		return err;
+
+	r = (v ? 0 : 1);
 
 	mutex_lock(&data->update_lock);
 	data->beep_enable = !r;
@@ -523,7 +581,12 @@ static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl520_data *data = i2c_get_clientdata(client);
-	u8 r = simple_strtoul(buf, NULL, 10);
+	unsigned long r;
+	int err;
+
+	err = kstrtoul(buf, 10, &r);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	r &= data->alarm_mask;
@@ -575,7 +638,11 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	unsigned long bit;
 
-	bit = simple_strtoul(buf, NULL, 10);
+	int err;
+
+	err = kstrtoul(buf, 10, &bit);
+	if (err)
+		return err;
 	if (bit & ~1)
 		return -EINVAL;
 
@@ -717,7 +784,8 @@ static int gl520_probe(struct i2c_client *client,
 	gl520_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group)))
+	err = sysfs_create_group(&client->dev.kobj, &gl520_group);
+	if (err)
 		goto exit_free;
 
 	if (data->two_temps) {
@@ -849,7 +917,8 @@ static struct gl520_data *gl520_update_device(struct device *dev)
 
 		data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
 		data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
-		data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f;
+		data->vid = gl520_read_value(client,
+					     GL520_REG_VID_INPUT) & 0x1f;
 
 		for (i = 0; i < 4; i++) {
 			data->in_input[i] = gl520_read_value(client,
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index 932da8a..4fcb867 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -96,14 +96,14 @@ int vid_from_reg(int val, u8 vrm)
 			vid = 1862500 - (val & 0x1f) * 25000;
 		if(val & 0x20)
 			vid -= 12500;
-		return((vid + 500) / 1000);
+		return (vid + 500) / 1000;
 
 	case 110:		/* Intel Conroe */
 				/* compute in uV, round to mV */
 		val &= 0xff;
 		if (val < 0x02 || val > 0xb2)
 			return 0;
-		return((1600000 - (val - 2) * 6250 + 500) / 1000);
+		return (1600000 - (val - 2) * 6250 + 500) / 1000;
 
 	case 24:		/* Athlon64 & Opteron */
 		val &= 0x1f;
@@ -118,38 +118,38 @@ int vid_from_reg(int val, u8 vrm)
 	case 91:		/* VRM 9.1 */
 	case 90:		/* VRM 9.0 */
 		val &= 0x1f;
-		return(val == 0x1f ? 0 :
-		                       1850 - val * 25);
+		return val == 0x1f ? 0 :
+		                       1850 - val * 25;
 
 	case 85:		/* VRM 8.5 */
 		val &= 0x1f;
-		return((val & 0x10  ? 25 : 0) +
+		return (val & 0x10  ? 25 : 0) +
 		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
-		       ((val & 0x0f) * 50));
+		       ((val & 0x0f) * 50);
 
 	case 84:		/* VRM 8.4 */
 		val &= 0x0f;
 				/* fall through */
 	case 82:		/* VRM 8.2 */
 		val &= 0x1f;
-		return(val == 0x1f ? 0 :
+		return val == 0x1f ? 0 :
 		       val & 0x10  ? 5100 - (val) * 100 :
-		                     2050 - (val) * 50);
+		                     2050 - (val) * 50;
 	case 17:		/* Intel IMVP-II */
 		val &= 0x1f;
-		return(val & 0x10 ? 975 - (val & 0xF) * 25 :
-				    1750 - val * 50);
+		return val & 0x10 ? 975 - (val & 0xF) * 25 :
+				    1750 - val * 50;
 	case 13:
 	case 131:
 		val &= 0x3f;
 		/* Exception for Eden ULV 500 MHz */
 		if (vrm == 131 && val == 0x3f)
 			val++;
-		return(1708 - val * 16);
+		return 1708 - val * 16;
 	case 14:		/* Intel Core */
 				/* compute in uV, round to mV */
 		val &= 0x7f;
-		return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
+		return val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000;
 	default:		/* report 0 for unknown */
 		if (vrm)
 			pr_warn("Requested unsupported VRM version (%u)\n",
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 6460487..b58a0ff 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -55,6 +55,7 @@ struct device *hwmon_device_register(struct device *dev)
 
 	return hwdev;
 }
+EXPORT_SYMBOL_GPL(hwmon_device_register);
 
 /**
  * hwmon_device_unregister - removes the previously registered class device
@@ -72,6 +73,7 @@ void hwmon_device_unregister(struct device *dev)
 		dev_dbg(dev->parent,
 			"hwmon_device_unregister() failed: bad class ID!\n");
 }
+EXPORT_SYMBOL_GPL(hwmon_device_unregister);
 
 static void __init hwmon_pci_quirks(void)
 {
@@ -119,9 +121,6 @@ static void __exit hwmon_exit(void)
 subsys_initcall(hwmon_init);
 module_exit(hwmon_exit);
 
-EXPORT_SYMBOL_GPL(hwmon_device_register);
-EXPORT_SYMBOL_GPL(hwmon_device_unregister);
-
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
 MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index d22f241..a18882c 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -159,8 +159,12 @@ static ssize_t store_amb_min(struct device *dev,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i5k_amb_data *data = dev_get_drvdata(dev);
-	unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+	unsigned long temp;
+	int ret = kstrtoul(buf, 10, &temp);
+	if (ret < 0)
+		return ret;
 
+	temp = temp / 500;
 	if (temp > 255)
 		temp = 255;
 
@@ -175,8 +179,12 @@ static ssize_t store_amb_mid(struct device *dev,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i5k_amb_data *data = dev_get_drvdata(dev);
-	unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+	unsigned long temp;
+	int ret = kstrtoul(buf, 10, &temp);
+	if (ret < 0)
+		return ret;
 
+	temp = temp / 500;
 	if (temp > 255)
 		temp = 255;
 
@@ -191,8 +199,12 @@ static ssize_t store_amb_max(struct device *dev,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i5k_amb_data *data = dev_get_drvdata(dev);
-	unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
+	unsigned long temp;
+	int ret = kstrtoul(buf, 10, &temp);
+	if (ret < 0)
+		return ret;
 
+	temp = temp / 500;
 	if (temp > 255)
 		temp = 255;
 
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index cc2981f..37f17e0 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -1045,7 +1045,7 @@ static struct aem_ro_sensor_template aem2_ro_sensors[] = {
 {"power6_average",	  aem2_show_pcap_value,	POWER_CAP_MIN_WARNING},
 {"power7_average",	  aem2_show_pcap_value,	POWER_CAP_MIN},
 
-{"power3_average", 	  aem2_show_pcap_value,	POWER_AUX},
+{"power3_average",	  aem2_show_pcap_value,	POWER_AUX},
 {"power_cap",		  aem2_show_pcap_value,	POWER_CAP},
 {NULL,                    NULL,                 0},
 };
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index 41aa6a3..aba29d6 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -205,7 +205,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)
 	pci_set_drvdata(pdev, NULL);
 }
 
-static const struct pci_device_id k10temp_id_table[] = {
+static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index b923bc2..5751019 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -46,7 +46,7 @@ struct k8temp_data {
 	unsigned long last_updated;	/* in jiffies */
 
 	/* registers values */
-	u8 sensorsp;		/* sensor presence bits - SEL_CORE & SEL_PLACE */
+	u8 sensorsp;		/* sensor presence bits - SEL_CORE, SEL_PLACE */
 	u32 temp[2][2];		/* core, place */
 	u8 swap_core_select;    /* meaning of SEL_CORE is inverted */
 	u32 temp_offset;
@@ -63,7 +63,7 @@ static struct k8temp_data *k8temp_update_device(struct device *dev)
 	if (!data->valid
 	    || time_after(jiffies, data->last_updated + HZ)) {
 		pci_read_config_byte(pdev, REG_TEMP, &tmp);
-		tmp &= ~(SEL_PLACE | SEL_CORE);		/* Select sensor 0, core0 */
+		tmp &= ~(SEL_PLACE | SEL_CORE);	/* Select sensor 0, core0 */
 		pci_write_config_byte(pdev, REG_TEMP, tmp);
 		pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]);
 
@@ -82,7 +82,7 @@ static struct k8temp_data *k8temp_update_device(struct device *dev)
 					      &data->temp[1][0]);
 
 			if (data->sensorsp & SEL_PLACE) {
-				tmp |= SEL_PLACE;	/* Select sensor 1, core1 */
+				tmp |= SEL_PLACE; /* Select sensor 1, core1 */
 				pci_write_config_byte(pdev, REG_TEMP, tmp);
 				pci_read_config_dword(pdev, REG_TEMP,
 						      &data->temp[1][1]);
@@ -136,7 +136,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
 static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-static const struct pci_device_id k8temp_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
 	{ 0 },
 };
@@ -183,7 +183,8 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
 	u8 model, stepping;
 	struct k8temp_data *data;
 
-	if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit;
 	}
@@ -217,7 +218,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
 		data->temp_offset = 21000;
 
 	pci_read_config_byte(pdev, REG_TEMP, &scfg);
-	scfg &= ~(SEL_PLACE | SEL_CORE);		/* Select sensor 0, core0 */
+	scfg &= ~(SEL_PLACE | SEL_CORE);	/* Select sensor 0, core0 */
 	pci_write_config_byte(pdev, REG_TEMP, scfg);
 	pci_read_config_byte(pdev, REG_TEMP, &scfg);
 
@@ -238,7 +239,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
 		pci_write_config_byte(pdev, REG_TEMP, scfg);
 		pci_read_config_dword(pdev, REG_TEMP, &temp);
 		scfg |= SEL_CORE;	/* prepare for next selection */
-		if (!((temp >> 16) & 0xff))	/* if temp is 0 -49C is not likely */
+		if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */
 			data->sensorsp &= ~SEL_PLACE;
 	}
 
@@ -246,7 +247,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
 		scfg &= ~SEL_PLACE;	/* Select sensor 0, core1 */
 		pci_write_config_byte(pdev, REG_TEMP, scfg);
 		pci_read_config_dword(pdev, REG_TEMP, &temp);
-		if (!((temp >> 16) & 0xff))	/* if temp is 0 -49C is not likely */
+		if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */
 			data->sensorsp &= ~SEL_CORE;
 	}
 
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index c274ea2..0994cb0 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -57,7 +57,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
 	struct spi_device *spi = to_spi_device(dev);
 	int status, val = 0;
 	u8 rxbuf[2];
-	s16 raw=0;
+	s16 raw = 0;
 	struct lm70 *p_lm70 = spi_get_drvdata(spi);
 
 	if (mutex_lock_interruptible(&p_lm70->lock))
diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c
index 8dfc678..08f7ffe 100644
--- a/drivers/hwmon/lm77.c
+++ b/drivers/hwmon/lm77.c
@@ -1,6 +1,6 @@
 /*
     lm77.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
+		monitoring
 
     Copyright (c) 2004  Andras BALI <drewie@freemail.hu>
 
@@ -49,7 +49,7 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
 
 /* Each client has this additional data */
 struct lm77_data {
-	struct device 		*hwmon_dev;
+	struct device		*hwmon_dev;
 	struct mutex		update_lock;
 	char			valid;
 	unsigned long		last_updated;	/* In jiffies */
@@ -112,7 +112,9 @@ static inline int LM77_TEMP_FROM_REG(s16 reg)
 
 /* read routines for temperature limits */
 #define show(value)	\
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)	\
+static ssize_t show_##value(struct device *dev,			\
+			    struct device_attribute *attr,	\
+			    char *buf)				\
 {								\
 	struct lm77_data *data = lm77_update_device(dev);	\
 	return sprintf(buf, "%d\n", data->value);		\
@@ -124,17 +126,20 @@ show(temp_min);
 show(temp_max);
 
 /* read routines for hysteresis values */
-static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_crit_hyst(struct device *dev,
+				   struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_crit - data->temp_hyst);
 }
-static ssize_t show_temp_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_min_hyst(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_min + data->temp_hyst);
 }
-static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_max_hyst(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_max - data->temp_hyst);
@@ -142,17 +147,21 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *a
 
 /* write routines */
 #define set(value, reg)	\
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
-{										\
-	struct i2c_client *client = to_i2c_client(dev);				\
-	struct lm77_data *data = i2c_get_clientdata(client);			\
-	long val = simple_strtol(buf, NULL, 10);				\
-										\
-	mutex_lock(&data->update_lock);						\
-	data->value = val;				\
-	lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value));		\
-	mutex_unlock(&data->update_lock);					\
-	return count;								\
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \
+			   const char *buf, size_t count)		\
+{									\
+	struct i2c_client *client = to_i2c_client(dev);			\
+	struct lm77_data *data = i2c_get_clientdata(client);		\
+	long val;							\
+	int err = kstrtol(buf, 10, &val);				\
+	if (err)							\
+		return err;						\
+									\
+	mutex_lock(&data->update_lock);					\
+	data->value = val;						\
+	lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value));	\
+	mutex_unlock(&data->update_lock);				\
+	return count;							\
 }
 
 set(temp_min, LM77_REG_TEMP_MIN);
@@ -160,11 +169,18 @@ set(temp_max, LM77_REG_TEMP_MAX);
 
 /* hysteresis is stored as a relative value on the chip, so it has to be
    converted first */
-static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_crit_hyst(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm77_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst = data->temp_crit - val;
@@ -175,13 +191,19 @@ static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *a
 }
 
 /* preserve hysteresis when setting T_crit */
-static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm77_data *data = i2c_get_clientdata(client);
-	long val = simple_strtoul(buf, NULL, 10);
 	int oldcrithyst;
-	
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
 	mutex_lock(&data->update_lock);
 	oldcrithyst = data->temp_crit - data->temp_hyst;
 	data->temp_crit = val;
@@ -330,7 +352,8 @@ static int lm77_probe(struct i2c_client *new_client,
 	lm77_init_client(new_client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &lm77_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 6df0b46..84f99e2 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -1,7 +1,7 @@
 /*
     lm78.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
-    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> 
+	monitoring
+    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
     Copyright (c) 2007, 2011  Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
@@ -74,8 +74,10 @@ enum chips { lm78, lm79 };
 #define LM78_REG_I2C_ADDR 0x48
 
 
-/* Conversions. Rounding and limit checking is only done on the TO_REG 
-   variants. */
+/*
+ * Conversions. Rounding and limit checking is only done on the TO_REG
+ * variants.
+ */
 
 /* IN: mV, (0V to 4.08V)
    REG: 16mV/bit */
@@ -95,7 +97,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 
 static inline int FAN_FROM_REG(u8 val, int div)
 {
-	return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
+	return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
 }
 
 /* TEMP: mC (-128C to +127C)
@@ -103,7 +105,7 @@ static inline int FAN_FROM_REG(u8 val, int div)
 static inline s8 TEMP_TO_REG(int val)
 {
 	int nval = SENSORS_LIMIT(val, -128000, 127000) ;
-	return nval<0 ? (nval-500)/1000 : (nval+500)/1000;
+	return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000;
 }
 
 static inline int TEMP_FROM_REG(s8 val)
@@ -177,8 +179,13 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm78_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int nr = attr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
@@ -192,8 +199,13 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm78_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int nr = attr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
@@ -201,7 +213,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-	
+
 #define show_in_offset(offset)					\
 static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
 		show_in, NULL, offset);				\
@@ -237,7 +249,12 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
 			     const char *buf, size_t count)
 {
 	struct lm78_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_over = TEMP_TO_REG(val);
@@ -257,7 +274,12 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
 			     const char *buf, size_t count)
 {
 	struct lm78_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst = TEMP_TO_REG(val);
@@ -280,7 +302,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da,
 	struct lm78_data *data = lm78_update_device(dev);
 	int nr = attr->index;
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
-		DIV_FROM_REG(data->fan_div[nr])) );
+		DIV_FROM_REG(data->fan_div[nr])));
 }
 
 static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
@@ -289,8 +311,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm78_data *data = lm78_update_device(dev);
 	int nr = attr->index;
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
-		DIV_FROM_REG(data->fan_div[nr])) );
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+		DIV_FROM_REG(data->fan_div[nr])));
 }
 
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
@@ -299,7 +321,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm78_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -326,19 +353,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct lm78_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	unsigned long min;
 	u8 reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
 			   DIV_FROM_REG(data->fan_div[nr]));
 
 	switch (val) {
-	case 1: data->fan_div[nr] = 0; break;
-	case 2: data->fan_div[nr] = 1; break;
-	case 4: data->fan_div[nr] = 2; break;
-	case 8: data->fan_div[nr] = 3; break;
+	case 1:
+		data->fan_div[nr] = 0;
+		break;
+	case 2:
+		data->fan_div[nr] = 1;
+		break;
+	case 4:
+		data->fan_div[nr] = 2;
+		break;
+	case 8:
+		data->fan_div[nr] = 3;
+		break;
 	default:
 		dev_err(dev, "fan_div value %ld not "
 			"supported. Choose one of 1, 2, 4 or 8!\n", val);
@@ -669,11 +709,13 @@ static struct i2c_driver lm78_driver = {
 	.address_list	= normal_i2c,
 };
 
-/* The SMBus locks itself, but ISA access must be locked explicitly! 
-   We don't want to lock the whole ISA bus, so we lock each client
-   separately.
-   We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the LM78 access and should not be necessary.  */
+/*
+ * The SMBus locks itself, but ISA access must be locked explicitly!
+ * We don't want to lock the whole ISA bus, so we lock each client
+ * separately.
+ * We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
+ * would slow down the LM78 access and should not be necessary.
+ */
 static int lm78_read_value(struct lm78_data *data, u8 reg)
 {
 	struct i2c_client *client = data->client;
@@ -691,11 +733,11 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitly! 
+/* The SMBus locks itself, but ISA access muse be locked explicitly!
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the LM78 access and should not be necessary. 
+   would slow down the LM78 access and should not be necessary.
    There are some ugly typecasts here, but the good new is - they should
    nowhere else be necessary! */
 static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
@@ -823,8 +865,11 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
 	lm78_init_device(data);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
-	 || (err = device_create_file(&pdev->dev, &dev_attr_name)))
+	err = sysfs_create_group(&pdev->dev.kobj, &lm78_group);
+	if (err)
+		goto exit_remove_files;
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
 		goto exit_remove_files;
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index 0891b38..dc6df4e 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -108,6 +108,7 @@ static inline long TEMP_FROM_REG(u16 temp)
 struct lm80_data {
 	struct device *hwmon_dev;
 	struct mutex update_lock;
+	char error;		/* !=0 if error occurred during last update */
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
@@ -170,6 +171,8 @@ static ssize_t show_in_##suffix(struct device *dev, \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct lm80_data *data = lm80_update_device(dev); \
+	if (IS_ERR(data)) \
+		return PTR_ERR(data); \
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \
 }
 show_in(min, in_min)
@@ -183,7 +186,10 @@ static ssize_t set_in_##suffix(struct device *dev, \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm80_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
+	long val; \
+	int err = kstrtol(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 \
 	mutex_lock(&data->update_lock);\
 	data->value[nr] = IN_TO_REG(val); \
@@ -200,6 +206,8 @@ static ssize_t show_fan_##suffix(struct device *dev, \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct lm80_data *data = lm80_update_device(dev); \
+	if (IS_ERR(data)) \
+		return PTR_ERR(data); \
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \
 		       DIV_FROM_REG(data->fan_div[nr]))); \
 }
@@ -211,6 +219,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
 {
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct lm80_data *data = lm80_update_device(dev);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
 
@@ -220,7 +230,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm80_data *data = i2c_get_clientdata(client);
-	long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -239,8 +252,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm80_data *data = i2c_get_clientdata(client);
-	unsigned long min, val = simple_strtoul(buf, NULL, 10);
+	unsigned long min, val;
 	u8 reg;
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
 
 	/* Save fan_min */
 	mutex_lock(&data->update_lock);
@@ -283,6 +299,8 @@ static ssize_t show_temp_input1(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
 }
 
@@ -291,6 +309,8 @@ static ssize_t show_temp_##suffix(struct device *dev, \
 	struct device_attribute *attr, char *buf) \
 { \
 	struct lm80_data *data = lm80_update_device(dev); \
+	if (IS_ERR(data)) \
+		return PTR_ERR(data); \
 	return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
 }
 show_temp(hot_max, temp_hot_max);
@@ -304,7 +324,10 @@ static ssize_t set_temp_##suffix(struct device *dev, \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm80_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtoul(buf, NULL, 10); \
+	long val; \
+	int err = kstrtol(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 \
 	mutex_lock(&data->update_lock); \
 	data->value = TEMP_LIMIT_TO_REG(val); \
@@ -321,6 +344,8 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 	return sprintf(buf, "%u\n", data->alarms);
 }
 
@@ -329,6 +354,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 {
 	int bitnr = to_sensor_dev_attr(attr)->index;
 	struct lm80_data *data = lm80_update_device(dev);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 	return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
 }
 
@@ -563,50 +590,111 @@ static struct lm80_data *lm80_update_device(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm80_data *data = i2c_get_clientdata(client);
 	int i;
+	int rv;
+	int prev_rv;
+	struct lm80_data *ret = data;
 
 	mutex_lock(&data->update_lock);
 
+	if (data->error)
+		lm80_init_client(client);
+
 	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
 		dev_dbg(&client->dev, "Starting lm80 update\n");
 		for (i = 0; i <= 6; i++) {
-			data->in[i] =
-			    lm80_read_value(client, LM80_REG_IN(i));
-			data->in_min[i] =
-			    lm80_read_value(client, LM80_REG_IN_MIN(i));
-			data->in_max[i] =
-			    lm80_read_value(client, LM80_REG_IN_MAX(i));
+			rv = lm80_read_value(client, LM80_REG_IN(i));
+			if (rv < 0)
+				goto abort;
+			data->in[i] = rv;
+
+			rv = lm80_read_value(client, LM80_REG_IN_MIN(i));
+			if (rv < 0)
+				goto abort;
+			data->in_min[i] = rv;
+
+			rv = lm80_read_value(client, LM80_REG_IN_MAX(i));
+			if (rv < 0)
+				goto abort;
+			data->in_max[i] = rv;
 		}
-		data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
-		data->fan_min[0] =
-		    lm80_read_value(client, LM80_REG_FAN_MIN(1));
-		data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
-		data->fan_min[1] =
-		    lm80_read_value(client, LM80_REG_FAN_MIN(2));
-
-		data->temp =
-		    (lm80_read_value(client, LM80_REG_TEMP) << 8) |
-		    (lm80_read_value(client, LM80_REG_RES) & 0xf0);
-		data->temp_os_max =
-		    lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
-		data->temp_os_hyst =
-		    lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
-		data->temp_hot_max =
-		    lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
-		data->temp_hot_hyst =
-		    lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
-
-		i = lm80_read_value(client, LM80_REG_FANDIV);
-		data->fan_div[0] = (i >> 2) & 0x03;
-		data->fan_div[1] = (i >> 4) & 0x03;
-		data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
-		    (lm80_read_value(client, LM80_REG_ALARM2) << 8);
+
+		rv = lm80_read_value(client, LM80_REG_FAN1);
+		if (rv < 0)
+			goto abort;
+		data->fan[0] = rv;
+
+		rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+		if (rv < 0)
+			goto abort;
+		data->fan_min[0] = rv;
+
+		rv = lm80_read_value(client, LM80_REG_FAN2);
+		if (rv < 0)
+			goto abort;
+		data->fan[1] = rv;
+
+		rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
+		if (rv < 0)
+			goto abort;
+		data->fan_min[1] = rv;
+
+		prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP);
+		if (rv < 0)
+			goto abort;
+		rv = lm80_read_value(client, LM80_REG_RES);
+		if (rv < 0)
+			goto abort;
+		data->temp = (prev_rv << 8) | (rv & 0xf0);
+
+		rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
+		if (rv < 0)
+			goto abort;
+		data->temp_os_max = rv;
+
+		rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
+		if (rv < 0)
+			goto abort;
+		data->temp_os_hyst = rv;
+
+		rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
+		if (rv < 0)
+			goto abort;
+		data->temp_hot_max = rv;
+
+		rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
+		if (rv < 0)
+			goto abort;
+		data->temp_hot_hyst = rv;
+
+		rv = lm80_read_value(client, LM80_REG_FANDIV);
+		if (rv < 0)
+			goto abort;
+		data->fan_div[0] = (rv >> 2) & 0x03;
+		data->fan_div[1] = (rv >> 4) & 0x03;
+
+		prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1);
+		if (rv < 0)
+			goto abort;
+		rv = lm80_read_value(client, LM80_REG_ALARM2);
+		if (rv < 0)
+			goto abort;
+		data->alarms = prev_rv + (rv << 8);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
+		data->error = 0;
 	}
+	goto done;
+
+abort:
+	ret = ERR_PTR(rv);
+	data->valid = 0;
+	data->error = 1;
 
+done:
 	mutex_unlock(&data->update_lock);
 
-	return data;
+	return ret;
 }
 
 static int __init sensors_lm80_init(void)
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index 8290476..1fed265 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -124,7 +124,7 @@ static struct lm83_data *lm83_update_device(struct device *dev);
 /*
  * Driver data (common to all clients)
  */
- 
+
 static const struct i2c_device_id lm83_id[] = {
 	{ "lm83", lm83 },
 	{ "lm82", lm82 },
@@ -179,8 +179,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm83_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
 	int nr = attr->index;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp[nr] = TEMP_TO_REG(val);
@@ -355,12 +360,14 @@ static int lm83_probe(struct i2c_client *new_client,
 	 * declare 1 and 3 common, and then 2 and 4 only for the LM83.
 	 */
 
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &lm83_group);
+	if (err)
 		goto exit_free;
 
 	if (id->driver_data == lm83) {
-		if ((err = sysfs_create_group(&new_client->dev.kobj,
-					      &lm83_group_opt)))
+		err = sysfs_create_group(&new_client->dev.kobj,
+					 &lm83_group_opt);
+		if (err)
 			goto exit_remove_files;
 	}
 
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index da72dc1..240b7f9 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -1,6 +1,6 @@
 /*
     lm85.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
+	monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
     Copyright (c) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
     Copyright (c) 2003        Margit Schubert-While <margitsw@t-online.de>
@@ -391,7 +391,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val);
@@ -443,7 +448,14 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct lm85_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 
@@ -500,7 +512,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = PWM_TO_REG(val);
@@ -537,8 +554,13 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
 	u8 config;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	switch (val) {
 	case 0:
@@ -588,7 +610,12 @@ static ssize_t set_pwm_freq(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	/* The ADT7468 has a special high-frequency PWM output mode,
@@ -648,7 +675,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = INS_TO_REG(nr, val);
@@ -671,7 +703,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = INS_TO_REG(nr, val);
@@ -722,7 +759,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (IS_ADT7468_OFF64(data))
 		val += 64;
@@ -748,7 +790,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (IS_ADT7468_OFF64(data))
 		val += 64;
@@ -789,7 +836,12 @@ static ssize_t set_pwm_auto_channels(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->autofan[nr].config = (data->autofan[nr].config & (~0xe0))
@@ -814,7 +866,12 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->autofan[nr].min_pwm = PWM_TO_REG(val);
@@ -838,8 +895,13 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
 	u8 tmp;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->autofan[nr].min_off = val;
@@ -885,7 +947,12 @@ static ssize_t set_temp_auto_temp_off(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
 	int min;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	min = TEMP_FROM_REG(data->zone[nr].limit);
@@ -916,7 +983,12 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->zone[nr].limit = TEMP_TO_REG(val);
@@ -951,7 +1023,12 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
 	int min;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	min = TEMP_FROM_REG(data->zone[nr].limit);
@@ -979,7 +1056,12 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm85_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->zone[nr].critical = TEMP_TO_REG(val);
@@ -1346,16 +1428,18 @@ static int lm85_probe(struct i2c_client *client,
 			data->has_vid5 = true;
 	}
 
-	if (!data->has_vid5)
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					&lm85_group_in4)))
+	if (!data->has_vid5) {
+		err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4);
+		if (err)
 			goto err_remove_files;
+	}
 
 	/* The EMC6D100 has 3 additional voltage inputs */
-	if (data->type == emc6d100)
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					&lm85_group_in567)))
+	if (data->type == emc6d100) {
+		err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567);
+		if (err)
 			goto err_remove_files;
+	}
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index f1e6e75..ebf4efd 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -119,20 +119,21 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C };
  * The LM87 uses signed 8-bit values for temperatures.
  */
 
-#define IN_FROM_REG(reg,scale)	(((reg) * (scale) + 96) / 192)
-#define IN_TO_REG(val,scale)	((val) <= 0 ? 0 : \
+#define IN_FROM_REG(reg, scale)	(((reg) * (scale) + 96) / 192)
+#define IN_TO_REG(val, scale)	((val) <= 0 ? 0 : \
 				 (val) * 192 >= (scale) * 255 ? 255 : \
-				 ((val) * 192 + (scale)/2) / (scale))
+				 ((val) * 192 + (scale) / 2) / (scale))
 
 #define TEMP_FROM_REG(reg)	((reg) * 1000)
 #define TEMP_TO_REG(val)	((val) <= -127500 ? -128 : \
 				 (val) >= 126500 ? 127 : \
-				 (((val) < 0 ? (val)-500 : (val)+500) / 1000))
+				 (((val) < 0 ? (val) - 500 : \
+				   (val) + 500) / 1000))
 
-#define FAN_FROM_REG(reg,div)	((reg) == 255 || (reg) == 0 ? 0 : \
-				 (1350000 + (reg)*(div) / 2) / ((reg)*(div)))
-#define FAN_TO_REG(val,div)	((val)*(div) * 255 <= 1350000 ? 255 : \
-				 (1350000 + (val)*(div) / 2) / ((val)*(div)))
+#define FAN_FROM_REG(reg, div)	((reg) == 255 || (reg) == 0 ? 0 : \
+				 (1350000 + (reg)*(div) / 2) / ((reg) * (div)))
+#define FAN_TO_REG(val, div)	((val) * (div) * 255 <= 1350000 ? 255 : \
+				 (1350000 + (val)*(div) / 2) / ((val) * (div)))
 
 #define FAN_DIV_FROM_REG(reg)	(1 << (reg))
 
@@ -232,19 +233,23 @@ static inline int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
 }
 
 #define show_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_in##offset##_input(struct device *dev, \
+				       struct device_attribute *attr, \
+				       char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
 		       data->in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, \
+				     struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
 		       data->in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, \
+				     struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
@@ -261,44 +266,58 @@ show_in(5);
 show_in(6);
 show_in(7);
 
-static void set_in_min(struct device *dev, const char *buf, int nr)
+static ssize_t set_in_min(struct device *dev, const char *buf, int nr,
+			  size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]);
-	lm87_write_value(client, nr<6 ? LM87_REG_IN_MIN(nr) :
-			 LM87_REG_AIN_MIN(nr-6), data->in_min[nr]);
+	lm87_write_value(client, nr < 6 ? LM87_REG_IN_MIN(nr) :
+			 LM87_REG_AIN_MIN(nr - 6), data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
+	return count;
 }
 
-static void set_in_max(struct device *dev, const char *buf, int nr)
+static ssize_t set_in_max(struct device *dev, const char *buf, int nr,
+			  size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]);
-	lm87_write_value(client, nr<6 ? LM87_REG_IN_MAX(nr) :
-			 LM87_REG_AIN_MAX(nr-6), data->in_max[nr]);
+	lm87_write_value(client, nr < 6 ? LM87_REG_IN_MAX(nr) :
+			 LM87_REG_AIN_MAX(nr - 6), data->in_max[nr]);
 	mutex_unlock(&data->update_lock);
+	return count;
 }
 
 #define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, \
+static ssize_t set_in##offset##_min(struct device *dev, \
+				    struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
-	set_in_min(dev, buf, offset); \
-	return count; \
+	return set_in_min(dev, buf, offset, count); \
 } \
-static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, \
+static ssize_t set_in##offset##_max(struct device *dev, \
+				    struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
-	set_in_max(dev, buf, offset); \
-	return count; \
+	return set_in_max(dev, buf, offset, count); \
 } \
 static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
 		show_in##offset##_min, set_in##offset##_min); \
@@ -314,63 +333,85 @@ set_in(6);
 set_in(7);
 
 #define show_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, \
+					 struct device_attribute *attr, \
+					 char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset - 1])); \
 } \
-static ssize_t show_temp##offset##_low(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_temp##offset##_low(struct device *dev, \
+				       struct device_attribute *attr, \
+				       char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[offset-1])); \
+	return sprintf(buf, "%d\n", \
+		       TEMP_FROM_REG(data->temp_low[offset - 1])); \
 } \
-static ssize_t show_temp##offset##_high(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_temp##offset##_high(struct device *dev, \
+					struct device_attribute *attr, \
+					char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[offset-1])); \
-}\
+	return sprintf(buf, "%d\n", \
+		       TEMP_FROM_REG(data->temp_high[offset - 1])); \
+} \
 static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
 		show_temp##offset##_input, NULL);
 show_temp(1);
 show_temp(2);
 show_temp(3);
 
-static void set_temp_low(struct device *dev, const char *buf, int nr)
+static ssize_t set_temp_low(struct device *dev, const char *buf, int nr,
+			    size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_low[nr] = TEMP_TO_REG(val);
 	lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
 	mutex_unlock(&data->update_lock);
+	return count;
 }
 
-static void set_temp_high(struct device *dev, const char *buf, int nr)
+static ssize_t set_temp_high(struct device *dev, const char *buf, int nr,
+			     size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_high[nr] = TEMP_TO_REG(val);
 	lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
 	mutex_unlock(&data->update_lock);
+	return count;
 }
 
 #define set_temp(offset) \
-static ssize_t set_temp##offset##_low(struct device *dev, struct device_attribute *attr, \
+static ssize_t set_temp##offset##_low(struct device *dev, \
+				      struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
-	set_temp_low(dev, buf, offset-1); \
-	return count; \
+	return set_temp_low(dev, buf, offset - 1, count); \
 } \
-static ssize_t set_temp##offset##_high(struct device *dev, struct device_attribute *attr, \
+static ssize_t set_temp##offset##_high(struct device *dev, \
+				       struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
-	set_temp_high(dev, buf, offset-1); \
-	return count; \
+	return set_temp_high(dev, buf, offset - 1, count); \
 } \
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
 		show_temp##offset##_high, set_temp##offset##_high); \
@@ -380,13 +421,15 @@ set_temp(1);
 set_temp(2);
 set_temp(3);
 
-static ssize_t show_temp_crit_int(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_crit_int(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_int));
 }
 
-static ssize_t show_temp_crit_ext(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_crit_ext(struct device *dev,
+				  struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_ext));
@@ -397,39 +440,53 @@ static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit_ext, NULL);
 static DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit_ext, NULL);
 
 #define show_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_fan##offset##_input(struct device *dev, \
+					struct device_attribute *attr, \
+					char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[offset-1], \
-		       FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[offset - 1], \
+		       FAN_DIV_FROM_REG(data->fan_div[offset - 1]))); \
 } \
-static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, \
+				      struct device_attribute *attr, \
+				      char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[offset-1], \
-		       FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[offset - 1], \
+		       FAN_DIV_FROM_REG(data->fan_div[offset - 1]))); \
 } \
-static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, \
+				      struct device_attribute *attr, \
+				      char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
-	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[offset-1])); \
+	return sprintf(buf, "%d\n", \
+		       FAN_DIV_FROM_REG(data->fan_div[offset - 1])); \
 } \
 static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
 		show_fan##offset##_input, NULL);
 show_fan(1);
 show_fan(2);
 
-static void set_fan_min(struct device *dev, const char *buf, int nr)
+static ssize_t set_fan_min(struct device *dev, const char *buf, int nr,
+			   size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val,
 			    FAN_DIV_FROM_REG(data->fan_div[nr]));
 	lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
+	return count;
 }
 
 /* Note: we save and restore the fan minimum here, because its value is
@@ -441,19 +498,32 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
 	unsigned long min;
 	u8 reg;
 
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
+
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
 			   FAN_DIV_FROM_REG(data->fan_div[nr]));
 
 	switch (val) {
-	case 1: data->fan_div[nr] = 0; break;
-	case 2: data->fan_div[nr] = 1; break;
-	case 4: data->fan_div[nr] = 2; break;
-	case 8: data->fan_div[nr] = 3; break;
+	case 1:
+		data->fan_div[nr] = 0;
+		break;
+	case 2:
+		data->fan_div[nr] = 1;
+		break;
+	case 4:
+		data->fan_div[nr] = 2;
+		break;
+	case 8:
+		data->fan_div[nr] = 3;
+		break;
 	default:
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -479,16 +549,19 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
 }
 
 #define set_fan(offset) \
-static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, \
+				     struct device_attribute *attr, \
+				     const char *buf, \
 		size_t count) \
 { \
-	set_fan_min(dev, buf, offset-1); \
-	return count; \
+	return set_fan_min(dev, buf, offset - 1, count); \
 } \
-static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
+static ssize_t set_fan##offset##_div(struct device *dev, \
+				     struct device_attribute *attr, \
+				     const char *buf, \
 		size_t count) \
 { \
-	return set_fan_div(dev, buf, count, offset-1); \
+	return set_fan_div(dev, buf, count, offset - 1); \
 } \
 static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
 		show_fan##offset##_min, set_fan##offset##_min); \
@@ -497,43 +570,60 @@ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
 set_fan(1);
 set_fan(2);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+			char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+			char *buf)
 {
 	struct lm87_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
 {
 	struct lm87_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 
-static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
 }
-static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->aout = AOUT_TO_REG(val);
@@ -721,7 +811,8 @@ static int lm87_probe(struct i2c_client *new_client,
 	data->in_scale[7] = 1875;
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm87_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &lm87_group);
+	if (err)
 		goto exit_free;
 
 	if (data->channel & CHAN_NO_FAN(0)) {
diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c
index 8fcbd4d4..95cda41 100644
--- a/drivers/hwmon/lm92.c
+++ b/drivers/hwmon/lm92.c
@@ -138,7 +138,8 @@ static struct lm92_data *lm92_update_device(struct device *dev)
 }
 
 #define show_temp(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, \
+			    char *buf) \
 { \
 	struct lm92_data *data = lm92_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -149,13 +150,17 @@ show_temp(temp1_min);
 show_temp(temp1_max);
 
 #define set_temp(value, reg) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \
+			   const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm92_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
+	long val; \
+	int err = kstrtol(buf, 10, &val); \
+	if (err) \
+		return err; \
+\
 	mutex_lock(&data->update_lock); \
 	data->value = TEMP_TO_REG(val); \
 	i2c_smbus_write_word_swapped(client, reg, data->value); \
@@ -166,31 +171,40 @@ set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
 set_temp(temp1_min, LM92_REG_TEMP_LOW);
 set_temp(temp1_max, LM92_REG_TEMP_HIGH);
 
-static ssize_t show_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp1_crit_hyst(struct device *dev,
+				    struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
 		       - TEMP_FROM_REG(data->temp1_hyst));
 }
-static ssize_t show_temp1_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp1_max_hyst(struct device *dev,
+				   struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
 		       - TEMP_FROM_REG(data->temp1_hyst));
 }
-static ssize_t show_temp1_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp1_min_hyst(struct device *dev,
+				   struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
 		       + TEMP_FROM_REG(data->temp1_hyst));
 }
 
-static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf,
-	size_t count)
+static ssize_t set_temp1_crit_hyst(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm92_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val;
@@ -200,7 +214,8 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *
 	return count;
 }
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
@@ -265,7 +280,7 @@ static int max6635_check(struct i2c_client *client)
 	temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
 	if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
 		return 0;
-	
+
 	/* Limits are stored as integer values (signed, 9-bit). */
 	if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
 		return 0;
@@ -279,17 +294,17 @@ static int max6635_check(struct i2c_client *client)
 	   reads and time, but this should still be sufficient to dismiss
 	   non-MAX6635 chips. */
 	conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
-	for (i=16; i<96; i*=2) {
+	for (i = 16; i < 96; i *= 2) {
 		if (temp_hyst != i2c_smbus_read_word_data(client,
-		 		 LM92_REG_TEMP_HYST + i - 16)
+				 LM92_REG_TEMP_HYST + i - 16)
 		 || temp_crit != i2c_smbus_read_word_data(client,
-		 		 LM92_REG_TEMP_CRIT + i)
+				 LM92_REG_TEMP_CRIT + i)
 		 || temp_low != i2c_smbus_read_word_data(client,
 				LM92_REG_TEMP_LOW + i + 16)
 		 || temp_high != i2c_smbus_read_word_data(client,
-		 		 LM92_REG_TEMP_HIGH + i + 32)
+				 LM92_REG_TEMP_HIGH + i + 32)
 		 || conf != i2c_smbus_read_byte_data(client,
-		 	    LM92_REG_CONFIG + i))
+			    LM92_REG_CONFIG + i))
 			return 0;
 	}
 
@@ -362,7 +377,8 @@ static int lm92_probe(struct i2c_client *new_client,
 	lm92_init_client(new_client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &lm92_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index 8bd6c5c..d2fc4ac 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -18,10 +18,10 @@
 	Copyright (c) 2005 Aspen Systems, Inc.
 
     Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org>
-        Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab
+	Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab
 
     Modified for mainline integration by Hans J. Koch <hjk@hansjkoch.de>
-        Copyright (c) 2007 Hans J. Koch, Linutronix GmbH
+	Copyright (c) 2007 Hans J. Koch, Linutronix GmbH
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -83,7 +83,7 @@
 #define LM93_REG_FAN_MIN(nr)		(0xb4 + (nr) * 2)
 
 /* pwm outputs: pwm1-pwm2 (nr => 0-1, reg => 0-3) */
-#define LM93_REG_PWM_CTL(nr,reg)	(0xc8 + (reg) + (nr) * 4)
+#define LM93_REG_PWM_CTL(nr, reg)	(0xc8 + (reg) + (nr) * 4)
 #define LM93_PWM_CTL1	0x0
 #define LM93_PWM_CTL2	0x1
 #define LM93_PWM_CTL3	0x2
@@ -160,7 +160,7 @@ static bool init;
 module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to non-zero to force chip initialization.");
 
-static int vccp_limit_type[2] = {0,0};
+static int vccp_limit_type[2] = {0, 0};
 module_param_array(vccp_limit_type, int, NULL, 0);
 MODULE_PARM_DESC(vccp_limit_type, "Configures in7 and in8 limit modes.");
 
@@ -386,8 +386,8 @@ static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
 	return (uV_vid + uV_offset + 5000) / 10000;
 }
 
-#define LM93_IN_MIN_FROM_REG(reg,vid)	LM93_IN_REL_FROM_REG(reg,0,vid)
-#define LM93_IN_MAX_FROM_REG(reg,vid)	LM93_IN_REL_FROM_REG(reg,1,vid)
+#define LM93_IN_MIN_FROM_REG(reg, vid)	LM93_IN_REL_FROM_REG((reg), 0, (vid))
+#define LM93_IN_MAX_FROM_REG(reg, vid)	LM93_IN_REL_FROM_REG((reg), 1, (vid))
 
 /* vid in mV , upper == 0 indicates low limit, otherwise upper limit
    upper also determines which nibble of the register is returned
@@ -412,14 +412,14 @@ static int LM93_TEMP_FROM_REG(u8 reg)
 }
 
 #define LM93_TEMP_MIN (-128000)
-#define LM93_TEMP_MAX ( 127000)
+#define LM93_TEMP_MAX (127000)
 
 /* TEMP: 1/1000 degrees C (-128C to +127C)
    REG: 1C/bit, two's complement */
 static u8 LM93_TEMP_TO_REG(long temp)
 {
 	int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX);
-	ntemp += (ntemp<0 ? -500 : 500);
+	ntemp += (ntemp < 0 ? -500 : 500);
 	return (u8)(ntemp / 1000);
 }
 
@@ -438,9 +438,9 @@ static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode)
 	return (reg & 0x0f) * (mode ? 5 : 10);
 }
 
-#define LM93_TEMP_OFFSET_MIN  (  0)
+#define LM93_TEMP_OFFSET_MIN  (0)
 #define LM93_TEMP_OFFSET_MAX0 (150)
-#define LM93_TEMP_OFFSET_MAX1 ( 75)
+#define LM93_TEMP_OFFSET_MAX1 (75)
 
 /* This function is common to all 4-bit temperature offsets
    returns 4 bits right justified
@@ -534,7 +534,8 @@ static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data, long hyst,
 
 /* PWM: 0-255 per sensors documentation
    REG: 0-13 as mapped below... right justified */
-typedef enum { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ } pwm_freq_t;
+enum pwm_freq { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ };
+
 static int lm93_pwm_map[2][16] = {
 	{
 		0x00, /*   0.00% */ 0x40, /*  25.00% */
@@ -558,13 +559,13 @@ static int lm93_pwm_map[2][16] = {
 	},
 };
 
-static int LM93_PWM_FROM_REG(u8 reg, pwm_freq_t freq)
+static int LM93_PWM_FROM_REG(u8 reg, enum pwm_freq freq)
 {
 	return lm93_pwm_map[freq][reg & 0x0f];
 }
 
 /* round up to nearest match */
-static u8 LM93_PWM_TO_REG(int pwm, pwm_freq_t freq)
+static u8 LM93_PWM_TO_REG(int pwm, enum pwm_freq freq)
 {
 	int i;
 	for (i = 0; i < 13; i++)
@@ -578,7 +579,7 @@ static u8 LM93_PWM_TO_REG(int pwm, pwm_freq_t freq)
 static int LM93_FAN_FROM_REG(u16 regs)
 {
 	const u16 count = le16_to_cpu(regs) >> 2;
-	return count==0 ? -1 : count==0x3fff ? 0: 1350000 / count;
+	return count == 0 ? -1 : count == 0x3fff ? 0 : 1350000 / count;
 }
 
 /*
@@ -772,11 +773,12 @@ static u8 lm93_read_byte(struct i2c_client *client, u8 reg)
 	int value, i;
 
 	/* retry in case of read errors */
-	for (i=1; i<=MAX_RETRIES; i++) {
-		if ((value = i2c_smbus_read_byte_data(client, reg)) >= 0) {
+	for (i = 1; i <= MAX_RETRIES; i++) {
+		value = i2c_smbus_read_byte_data(client, reg);
+		if (value >= 0) {
 			return value;
 		} else {
-			dev_warn(&client->dev,"lm93: read byte data failed, "
+			dev_warn(&client->dev, "lm93: read byte data failed, "
 				"address 0x%02x.\n", reg);
 			mdelay(i + 3);
 		}
@@ -784,7 +786,7 @@ static u8 lm93_read_byte(struct i2c_client *client, u8 reg)
 	}
 
 	/* <TODO> what to return in case of error? */
-	dev_err(&client->dev,"lm93: All read byte retries failed!!\n");
+	dev_err(&client->dev, "lm93: All read byte retries failed!!\n");
 	return 0;
 }
 
@@ -796,7 +798,7 @@ static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value)
 	result = i2c_smbus_write_byte_data(client, reg, value);
 
 	if (result < 0)
-		dev_warn(&client->dev,"lm93: write byte data failed, "
+		dev_warn(&client->dev, "lm93: write byte data failed, "
 			 "0x%02x at address 0x%02x.\n", value, reg);
 
 	return result;
@@ -807,11 +809,12 @@ static u16 lm93_read_word(struct i2c_client *client, u8 reg)
 	int value, i;
 
 	/* retry in case of read errors */
-	for (i=1; i<=MAX_RETRIES; i++) {
-		if ((value = i2c_smbus_read_word_data(client, reg)) >= 0) {
+	for (i = 1; i <= MAX_RETRIES; i++) {
+		value = i2c_smbus_read_word_data(client, reg);
+		if (value >= 0) {
 			return value;
 		} else {
-			dev_warn(&client->dev,"lm93: read word data failed, "
+			dev_warn(&client->dev, "lm93: read word data failed, "
 				 "address 0x%02x.\n", reg);
 			mdelay(i + 3);
 		}
@@ -819,7 +822,7 @@ static u16 lm93_read_word(struct i2c_client *client, u8 reg)
 	}
 
 	/* <TODO> what to return in case of error? */
-	dev_err(&client->dev,"lm93: All read word retries failed!!\n");
+	dev_err(&client->dev, "lm93: All read word retries failed!!\n");
 	return 0;
 }
 
@@ -831,7 +834,7 @@ static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value)
 	result = i2c_smbus_write_word_data(client, reg, value);
 
 	if (result < 0)
-		dev_warn(&client->dev,"lm93: write word data failed, "
+		dev_warn(&client->dev, "lm93: write word data failed, "
 			 "0x%04x at address 0x%02x.\n", value, reg);
 
 	return result;
@@ -846,7 +849,7 @@ static u8 lm93_block_buffer[I2C_SMBUS_BLOCK_MAX];
 */
 static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
 {
-	int i, result=0;
+	int i, result = 0;
 
 	for (i = 1; i <= MAX_RETRIES; i++) {
 		result = i2c_smbus_read_block_data(client,
@@ -855,18 +858,18 @@ static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
 		if (result == lm93_block_read_cmds[fbn].len) {
 			break;
 		} else {
-			dev_warn(&client->dev,"lm93: block read data failed, "
+			dev_warn(&client->dev, "lm93: block read data failed, "
 				 "command 0x%02x.\n",
 				 lm93_block_read_cmds[fbn].cmd);
 			mdelay(i + 3);
 		}
 	}
 
-	if (result == lm93_block_read_cmds[fbn].len) {
-		memcpy(values,lm93_block_buffer,lm93_block_read_cmds[fbn].len);
-	} else {
-		/* <TODO> what to do in case of error? */
-	}
+	if (result == lm93_block_read_cmds[fbn].len)
+		memcpy(values, lm93_block_buffer,
+		       lm93_block_read_cmds[fbn].len);
+
+	/* <TODO> what to do in case of error? */
 }
 
 static struct lm93_data *lm93_update_device(struct device *dev)
@@ -964,7 +967,7 @@ static void lm93_update_client_common(struct lm93_data *data,
 static void lm93_update_client_full(struct lm93_data *data,
 				    struct i2c_client *client)
 {
-	dev_dbg(&client->dev,"starting device update (block data enabled)\n");
+	dev_dbg(&client->dev, "starting device update (block data enabled)\n");
 
 	/* in1 - in16: values & limits */
 	lm93_read_block(client, 3, (u8 *)(data->block3));
@@ -996,10 +999,10 @@ static void lm93_update_client_full(struct lm93_data *data,
 static void lm93_update_client_min(struct lm93_data *data,
 				   struct i2c_client *client)
 {
-	int i,j;
+	int i, j;
 	u8 *ptr;
 
-	dev_dbg(&client->dev,"starting device update (block data disabled)\n");
+	dev_dbg(&client->dev, "starting device update (block data disabled)\n");
 
 	/* in1 - in16: values & limits */
 	for (i = 0; i < 16; i++) {
@@ -1037,7 +1040,7 @@ static void lm93_update_client_min(struct lm93_data *data,
 	for (i = 0; i < 2; i++) {
 		for (j = 0; j < 4; j++) {
 			data->block9[i][j] =
-				lm93_read_byte(client, LM93_REG_PWM_CTL(i,j));
+				lm93_read_byte(client, LM93_REG_PWM_CTL(i, j));
 		}
 	}
 
@@ -1097,14 +1100,13 @@ static ssize_t show_in_min(struct device *dev,
 	int vccp = nr - 6;
 	long rc, vid;
 
-	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+	if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) {
 		vid = LM93_VID_FROM_REG(data->vid[vccp]);
 		rc = LM93_IN_MIN_FROM_REG(data->vccp_limits[vccp], vid);
+	} else {
+		rc = LM93_IN_FROM_REG(nr, data->block7[nr].min);
 	}
-	else {
-		rc = LM93_IN_FROM_REG(nr, data->block7[nr].min); \
-	}
-	return sprintf(buf, "%ld\n", rc); \
+	return sprintf(buf, "%ld\n", rc);
 }
 
 static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
@@ -1113,20 +1115,24 @@ static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	int vccp = nr - 6;
 	long vid;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+	if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) {
 		vid = LM93_VID_FROM_REG(data->vid[vccp]);
 		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0xf0) |
 				LM93_IN_REL_TO_REG(val, 0, vid);
 		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),
 				data->vccp_limits[vccp]);
-	}
-	else {
-		data->block7[nr].min = LM93_IN_TO_REG(nr,val);
+	} else {
+		data->block7[nr].min = LM93_IN_TO_REG(nr, val);
 		lm93_write_byte(client, LM93_REG_IN_MIN(nr),
 				data->block7[nr].min);
 	}
@@ -1175,14 +1181,13 @@ static ssize_t show_in_max(struct device *dev,
 	int vccp = nr - 6;
 	long rc, vid;
 
-	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+	if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) {
 		vid = LM93_VID_FROM_REG(data->vid[vccp]);
-		rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp],vid);
-	}
-	else {
-		rc = LM93_IN_FROM_REG(nr,data->block7[nr].max); \
+		rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp], vid);
+	} else {
+		rc = LM93_IN_FROM_REG(nr, data->block7[nr].max);
 	}
-	return sprintf(buf,"%ld\n",rc); \
+	return sprintf(buf, "%ld\n", rc);
 }
 
 static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
@@ -1191,20 +1196,24 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	int vccp = nr - 6;
 	long vid;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+	if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) {
 		vid = LM93_VID_FROM_REG(data->vid[vccp]);
 		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0x0f) |
 				LM93_IN_REL_TO_REG(val, 1, vid);
 		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),
 				data->vccp_limits[vccp]);
-	}
-	else {
-		data->block7[nr].max = LM93_IN_TO_REG(nr,val);
+	} else {
+		data->block7[nr].max = LM93_IN_TO_REG(nr, val);
 		lm93_write_byte(client, LM93_REG_IN_MAX(nr),
 				data->block7[nr].max);
 	}
@@ -1250,7 +1259,7 @@ static ssize_t show_temp(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->block2[nr]));
+	return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block2[nr]));
 }
 
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
@@ -1262,7 +1271,7 @@ static ssize_t show_temp_min(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->temp_lim[nr].min));
+	return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].min));
 }
 
 static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
@@ -1271,7 +1280,12 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_lim[nr].min = LM93_TEMP_TO_REG(val);
@@ -1292,7 +1306,7 @@ static ssize_t show_temp_max(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->temp_lim[nr].max));
+	return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].max));
 }
 
 static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
@@ -1301,7 +1315,12 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_lim[nr].max = LM93_TEMP_TO_REG(val);
@@ -1322,7 +1341,7 @@ static ssize_t show_temp_auto_base(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->block10.base[nr]));
+	return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block10.base[nr]));
 }
 
 static ssize_t store_temp_auto_base(struct device *dev,
@@ -1332,7 +1351,12 @@ static ssize_t store_temp_auto_base(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->block10.base[nr] = LM93_TEMP_TO_REG(val);
@@ -1349,11 +1373,11 @@ static SENSOR_DEVICE_ATTR(temp3_auto_base, S_IWUSR | S_IRUGO,
 			  show_temp_auto_base, store_temp_auto_base, 2);
 
 static ssize_t show_temp_auto_boost(struct device *dev,
-				    struct device_attribute *attr,char *buf)
+				    struct device_attribute *attr, char *buf)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->boost[nr]));
+	return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->boost[nr]));
 }
 
 static ssize_t store_temp_auto_boost(struct device *dev,
@@ -1363,7 +1387,12 @@ static ssize_t store_temp_auto_boost(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->boost[nr] = LM93_TEMP_TO_REG(val);
@@ -1386,7 +1415,7 @@ static ssize_t show_temp_auto_boost_hyst(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
 	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		       LM93_AUTO_BOOST_HYST_FROM_REGS(data, nr, mode));
 }
 
@@ -1397,7 +1426,12 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	/* force 0.5C/bit mode */
@@ -1429,9 +1463,9 @@ static ssize_t show_temp_auto_offset(struct device *dev,
 	int ofs = s_attr->nr;
 	struct lm93_data *data = lm93_update_device(dev);
 	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 	       LM93_TEMP_AUTO_OFFSET_FROM_REG(data->block10.offset[ofs],
-					      nr,mode));
+					      nr, mode));
 }
 
 static ssize_t store_temp_auto_offset(struct device *dev,
@@ -1443,7 +1477,12 @@ static ssize_t store_temp_auto_offset(struct device *dev,
 	int ofs = s_attr->nr;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	/* force 0.5C/bit mode */
@@ -1539,7 +1578,7 @@ static ssize_t show_temp_auto_pwm_min(struct device *dev,
 	struct lm93_data *data = lm93_update_device(dev);
 	reg = data->auto_pwm_min_hyst[nr/2] >> 4 & 0x0f;
 	ctl4 = data->block9[nr][LM93_PWM_CTL4];
-	return sprintf(buf,"%d\n",LM93_PWM_FROM_REG(reg, (ctl4 & 0x07) ?
+	return sprintf(buf, "%d\n", LM93_PWM_FROM_REG(reg, (ctl4 & 0x07) ?
 				LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
 }
 
@@ -1550,12 +1589,17 @@ static ssize_t store_temp_auto_pwm_min(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 reg, ctl4;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	reg = lm93_read_byte(client, LM93_REG_PWM_MIN_HYST(nr));
-	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
 	reg = (reg & 0x0f) |
 		LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
 				LM93_PWM_MAP_LO_FREQ :
@@ -1582,8 +1626,8 @@ static ssize_t show_temp_auto_offset_hyst(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
 	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
-	return sprintf(buf,"%d\n",LM93_TEMP_OFFSET_FROM_REG(
-					data->auto_pwm_min_hyst[nr/2], mode));
+	return sprintf(buf, "%d\n", LM93_TEMP_OFFSET_FROM_REG(
+					data->auto_pwm_min_hyst[nr / 2], mode));
 }
 
 static ssize_t store_temp_auto_offset_hyst(struct device *dev,
@@ -1593,8 +1637,13 @@ static ssize_t store_temp_auto_offset_hyst(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	/* force 0.5C/bit mode */
@@ -1626,7 +1675,7 @@ static ssize_t show_fan_input(struct device *dev,
 	int nr = s_attr->index;
 	struct lm93_data *data = lm93_update_device(dev);
 
-	return sprintf(buf,"%d\n",LM93_FAN_FROM_REG(data->block5[nr]));
+	return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block5[nr]));
 }
 
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
@@ -1640,7 +1689,7 @@ static ssize_t show_fan_min(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
 
-	return sprintf(buf,"%d\n",LM93_FAN_FROM_REG(data->block8[nr]));
+	return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block8[nr]));
 }
 
 static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
@@ -1649,11 +1698,16 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->block8[nr] = LM93_FAN_TO_REG(val);
-	lm93_write_word(client,LM93_REG_FAN_MIN(nr),data->block8[nr]);
+	lm93_write_word(client, LM93_REG_FAN_MIN(nr), data->block8[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1694,7 +1748,7 @@ static ssize_t show_fan_smart_tach(struct device *dev,
 	/* if there's a mapping and it's enabled */
 	if (mapping && ((data->sfc2 >> nr) & 0x01))
 		rc = mapping;
-	return sprintf(buf,"%ld\n",rc);
+	return sprintf(buf, "%ld\n", rc);
 }
 
 /* helper function - must grab data->update_lock before calling
@@ -1724,7 +1778,12 @@ static ssize_t store_fan_smart_tach(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	/* sanity test, ignore the write otherwise */
@@ -1732,7 +1791,7 @@ static ssize_t store_fan_smart_tach(struct device *dev,
 		/* can't enable if pwm freq is 22.5KHz */
 		if (val) {
 			u8 ctl4 = lm93_read_byte(client,
-				LM93_REG_PWM_CTL(val-1,LM93_PWM_CTL4));
+				LM93_REG_PWM_CTL(val - 1, LM93_PWM_CTL4));
 			if ((ctl4 & 0x07) == 0)
 				val = 0;
 		}
@@ -1766,7 +1825,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
 	else /* show present h/w value if manual pwm disabled */
 		rc = LM93_PWM_FROM_REG(ctl2 >> 4, (ctl4 & 0x07) ?
 			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ);
-	return sprintf(buf,"%ld\n",rc);
+	return sprintf(buf, "%ld\n", rc);
 }
 
 static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
@@ -1775,19 +1834,24 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ctl2, ctl4;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	ctl2 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2));
-	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
-	ctl2 = (ctl2 & 0x0f) | LM93_PWM_TO_REG(val,(ctl4 & 0x07) ?
+	ctl2 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
+	ctl2 = (ctl2 & 0x0f) | LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
 			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ) << 4;
 	/* save user commanded value */
 	data->pwm_override[nr] = LM93_PWM_FROM_REG(ctl2 >> 4,
 			(ctl4 & 0x07) ?  LM93_PWM_MAP_LO_FREQ :
 			LM93_PWM_MAP_HI_FREQ);
-	lm93_write_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2),ctl2);
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2), ctl2);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1808,7 +1872,7 @@ static ssize_t show_pwm_enable(struct device *dev,
 		rc = ((ctl2 & 0xF0) == 0xF0) ? 0 : 1;
 	else
 		rc = 2;
-	return sprintf(buf,"%ld\n",rc);
+	return sprintf(buf, "%ld\n", rc);
 }
 
 static ssize_t store_pwm_enable(struct device *dev,
@@ -1818,26 +1882,33 @@ static ssize_t store_pwm_enable(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ctl2;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	ctl2 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2));
+	ctl2 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2));
 
 	switch (val) {
 	case 0:
 		ctl2 |= 0xF1; /* enable manual override, set PWM to max */
 		break;
-	case 1: ctl2 |= 0x01; /* enable manual override */
+	case 1:
+		ctl2 |= 0x01; /* enable manual override */
 		break;
-	case 2: ctl2 &= ~0x01; /* disable manual override */
+	case 2:
+		ctl2 &= ~0x01; /* disable manual override */
 		break;
 	default:
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
 
-	lm93_write_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2),ctl2);
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2), ctl2);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1855,7 +1926,7 @@ static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
 	u8 ctl4;
 
 	ctl4 = data->block9[nr][LM93_PWM_CTL4];
-	return sprintf(buf,"%d\n",LM93_PWM_FREQ_FROM_REG(ctl4));
+	return sprintf(buf, "%d\n", LM93_PWM_FREQ_FROM_REG(ctl4));
 }
 
 /* helper function - must grab data->update_lock before calling
@@ -1887,17 +1958,22 @@ static ssize_t store_pwm_freq(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ctl4;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	ctl4 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
 	ctl4 = (ctl4 & 0xf8) | LM93_PWM_FREQ_TO_REG(val);
 	data->block9[nr][LM93_PWM_CTL4] = ctl4;
 	/* ctl4 == 0 -> 22.5KHz -> disable smart tach */
 	if (!ctl4)
 		lm93_disable_fan_smart_tach(client, data, nr);
-	lm93_write_byte(client,	LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4), ctl4);
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4), ctl4);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1912,7 +1988,7 @@ static ssize_t show_pwm_auto_channels(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",data->block9[nr][LM93_PWM_CTL1]);
+	return sprintf(buf, "%d\n", data->block9[nr][LM93_PWM_CTL1]);
 }
 
 static ssize_t store_pwm_auto_channels(struct device *dev,
@@ -1922,11 +1998,16 @@ static ssize_t store_pwm_auto_channels(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->block9[nr][LM93_PWM_CTL1] = SENSORS_LIMIT(val, 0, 255);
-	lm93_write_byte(client,	LM93_REG_PWM_CTL(nr,LM93_PWM_CTL1),
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL1),
 				data->block9[nr][LM93_PWM_CTL1]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -1938,7 +2019,7 @@ static SENSOR_DEVICE_ATTR(pwm2_auto_channels, S_IWUSR | S_IRUGO,
 			  show_pwm_auto_channels, store_pwm_auto_channels, 1);
 
 static ssize_t show_pwm_auto_spinup_min(struct device *dev,
-				struct device_attribute *attr,char *buf)
+				struct device_attribute *attr, char *buf)
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
@@ -1946,7 +2027,7 @@ static ssize_t show_pwm_auto_spinup_min(struct device *dev,
 
 	ctl3 = data->block9[nr][LM93_PWM_CTL3];
 	ctl4 = data->block9[nr][LM93_PWM_CTL4];
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		       LM93_PWM_FROM_REG(ctl3 & 0x0f, (ctl4 & 0x07) ?
 			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
 }
@@ -1958,17 +2039,22 @@ static ssize_t store_pwm_auto_spinup_min(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ctl3, ctl4;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	ctl3 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
-	ctl4 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
-	ctl3 = (ctl3 & 0xf0) | 	LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
+	ctl3 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
+	ctl3 = (ctl3 & 0xf0) | LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
 			LM93_PWM_MAP_LO_FREQ :
 			LM93_PWM_MAP_HI_FREQ);
 	data->block9[nr][LM93_PWM_CTL3] = ctl3;
-	lm93_write_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1985,7 +2071,7 @@ static ssize_t show_pwm_auto_spinup_time(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_SPINUP_TIME_FROM_REG(
+	return sprintf(buf, "%d\n", LM93_SPINUP_TIME_FROM_REG(
 				data->block9[nr][LM93_PWM_CTL3]));
 }
 
@@ -1996,14 +2082,19 @@ static ssize_t store_pwm_auto_spinup_time(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ctl3;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	ctl3 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
+	ctl3 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
 	ctl3 = (ctl3 & 0x1f) | (LM93_SPINUP_TIME_TO_REG(val) << 5 & 0xe0);
 	data->block9[nr][LM93_PWM_CTL3] = ctl3;
-	lm93_write_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
+	lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -2019,7 +2110,7 @@ static ssize_t show_pwm_auto_prochot_ramp(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		       LM93_RAMP_FROM_REG(data->pwm_ramp_ctl >> 4 & 0x0f));
 }
 
@@ -2029,8 +2120,13 @@ static ssize_t store_pwm_auto_prochot_ramp(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ramp;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);
@@ -2048,7 +2144,7 @@ static ssize_t show_pwm_auto_vrdhot_ramp(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		       LM93_RAMP_FROM_REG(data->pwm_ramp_ctl & 0x0f));
 }
 
@@ -2058,8 +2154,13 @@ static ssize_t store_pwm_auto_vrdhot_ramp(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 ramp;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);
@@ -2078,7 +2179,7 @@ static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_VID_FROM_REG(data->vid[nr]));
+	return sprintf(buf, "%d\n", LM93_VID_FROM_REG(data->vid[nr]));
 }
 
 static SENSOR_DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL, 0);
@@ -2089,7 +2190,7 @@ static ssize_t show_prochot(struct device *dev, struct device_attribute *attr,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",data->block4[nr].cur);
+	return sprintf(buf, "%d\n", data->block4[nr].cur);
 }
 
 static SENSOR_DEVICE_ATTR(prochot1, S_IRUGO, show_prochot, NULL, 0);
@@ -2100,7 +2201,7 @@ static ssize_t show_prochot_avg(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",data->block4[nr].avg);
+	return sprintf(buf, "%d\n", data->block4[nr].avg);
 }
 
 static SENSOR_DEVICE_ATTR(prochot1_avg, S_IRUGO, show_prochot_avg, NULL, 0);
@@ -2111,7 +2212,7 @@ static ssize_t show_prochot_max(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",data->prochot_max[nr]);
+	return sprintf(buf, "%d\n", data->prochot_max[nr]);
 }
 
 static ssize_t store_prochot_max(struct device *dev,
@@ -2121,7 +2222,12 @@ static ssize_t store_prochot_max(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->prochot_max[nr] = LM93_PROCHOT_TO_REG(val);
@@ -2143,7 +2249,7 @@ static ssize_t show_prochot_override(struct device *dev,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		(data->prochot_override & prochot_override_mask[nr]) ? 1 : 0);
 }
 
@@ -2154,7 +2260,12 @@ static ssize_t store_prochot_override(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	if (val)
@@ -2178,11 +2289,11 @@ static ssize_t show_prochot_interval(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
 	u8 tmp;
-	if (nr==1)
+	if (nr == 1)
 		tmp = (data->prochot_interval & 0xf0) >> 4;
 	else
 		tmp = data->prochot_interval & 0x0f;
-	return sprintf(buf,"%d\n",LM93_INTERVAL_FROM_REG(tmp));
+	return sprintf(buf, "%d\n", LM93_INTERVAL_FROM_REG(tmp));
 }
 
 static ssize_t store_prochot_interval(struct device *dev,
@@ -2192,12 +2303,17 @@ static ssize_t store_prochot_interval(struct device *dev,
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 tmp;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	tmp = lm93_read_byte(client, LM93_REG_PROCHOT_INTERVAL);
-	if (nr==1)
+	if (nr == 1)
 		tmp = (tmp & 0x0f) | (LM93_INTERVAL_TO_REG(val) << 4);
 	else
 		tmp = (tmp & 0xf0) | LM93_INTERVAL_TO_REG(val);
@@ -2217,7 +2333,7 @@ static ssize_t show_prochot_override_duty_cycle(struct device *dev,
 						char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",data->prochot_override & 0x0f);
+	return sprintf(buf, "%d\n", data->prochot_override & 0x0f);
 }
 
 static ssize_t store_prochot_override_duty_cycle(struct device *dev,
@@ -2226,7 +2342,12 @@ static ssize_t store_prochot_override_duty_cycle(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->prochot_override = (data->prochot_override & 0xf0) |
@@ -2245,7 +2366,7 @@ static ssize_t show_prochot_short(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",(data->config & 0x10) ? 1 : 0);
+	return sprintf(buf, "%d\n", (data->config & 0x10) ? 1 : 0);
 }
 
 static ssize_t store_prochot_short(struct device *dev,
@@ -2254,7 +2375,12 @@ static ssize_t store_prochot_short(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm93_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	if (val)
@@ -2274,8 +2400,8 @@ static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr,
 {
 	int nr = (to_sensor_dev_attr(attr))->index;
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",
-		       data->block1.host_status_1 & (1 << (nr+4)) ? 1 : 0);
+	return sprintf(buf, "%d\n",
+		       data->block1.host_status_1 & (1 << (nr + 4)) ? 1 : 0);
 }
 
 static SENSOR_DEVICE_ATTR(vrdhot1, S_IRUGO, show_vrdhot, NULL, 0);
@@ -2285,7 +2411,7 @@ static ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
 				char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_GPI_FROM_REG(data->gpi));
+	return sprintf(buf, "%d\n", LM93_GPI_FROM_REG(data->gpi));
 }
 
 static DEVICE_ATTR(gpio, S_IRUGO, show_gpio, NULL);
@@ -2294,7 +2420,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
 				char *buf)
 {
 	struct lm93_data *data = lm93_update_device(dev);
-	return sprintf(buf,"%d\n",LM93_ALARMS_FROM_REG(data->block1));
+	return sprintf(buf, "%d\n", LM93_ALARMS_FROM_REG(data->block1));
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -2494,13 +2620,13 @@ static void lm93_init_client(struct i2c_client *client)
 	lm93_write_byte(client, LM93_REG_CONFIG, reg | 0x01);
 
 	/* spin until ready */
-	for (i=0; i<20; i++) {
+	for (i = 0; i < 20; i++) {
 		msleep(10);
 		if ((lm93_read_byte(client, LM93_REG_CONFIG) & 0x80) == 0x80)
 			return;
 	}
 
-	dev_warn(&client->dev,"timed out waiting for sensor "
+	dev_warn(&client->dev, "timed out waiting for sensor "
 		 "chip to signal ready!\n");
 }
 
@@ -2540,7 +2666,7 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info)
 	}
 
 	strlcpy(info->type, name, I2C_NAME_SIZE);
-	dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n",
+	dev_dbg(&adapter->dev, "loading %s at %d, 0x%02x\n",
 		client->name, i2c_adapter_id(client->adapter),
 		client->addr);
 
@@ -2593,7 +2719,7 @@ static int lm93_probe(struct i2c_client *client,
 
 	/* Register hwmon driver class */
 	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if ( !IS_ERR(data->hwmon_dev))
+	if (!IS_ERR(data->hwmon_dev))
 		return 0;
 
 	err = PTR_ERR(data->hwmon_dev);
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 022ded0..f19599f 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -125,7 +125,7 @@ struct max1619_data {
 	u8 temp_input2, temp_low2, temp_high2; /* remote */
 	u8 temp_crit2;
 	u8 temp_hyst2;
-	u8 alarms; 
+	u8 alarms;
 };
 
 /*
@@ -133,7 +133,8 @@ struct max1619_data {
  */
 
 #define show_temp(value) \
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, \
+			    char *buf) \
 { \
 	struct max1619_data *data = max1619_update_device(dev); \
 	return sprintf(buf, "%d\n", temp_from_reg(data->value)); \
@@ -146,13 +147,17 @@ show_temp(temp_crit2);
 show_temp(temp_hyst2);
 
 #define set_temp2(value, reg) \
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \
+			   const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct max1619_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
+	long val; \
+	int err = kstrtol(buf, 10, &val); \
+	if (err) \
+		return err; \
+\
 	mutex_lock(&data->update_lock); \
 	data->value = temp_to_reg(val); \
 	i2c_smbus_write_byte_data(client, reg, data->value); \
@@ -165,7 +170,8 @@ set_temp2(temp_high2, MAX1619_REG_W_REMOTE_HIGH);
 set_temp2(temp_crit2, MAX1619_REG_W_REMOTE_CRIT);
 set_temp2(temp_hyst2, MAX1619_REG_W_TCRIT_HYST);
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct max1619_data *data = max1619_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
@@ -275,7 +281,8 @@ static int max1619_probe(struct i2c_client *new_client,
 	max1619_init_client(new_client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
+	err = sysfs_create_group(&new_client->dev.kobj, &max1619_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c
index 2fc034a..159ce02 100644
--- a/drivers/hwmon/max6650.c
+++ b/drivers/hwmon/max6650.c
@@ -135,8 +135,7 @@ static struct i2c_driver max6650_driver = {
  * Client data (each client gets its own)
  */
 
-struct max6650_data
-{
+struct max6650_data {
 	struct device *hwmon_dev;
 	struct mutex update_lock;
 	int nr_fans;
@@ -238,8 +237,13 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct max6650_data *data = i2c_get_clientdata(client);
-	int rpm = simple_strtoul(buf, NULL, 10);
 	int kscale, ktach;
+	unsigned long rpm;
+	int err;
+
+	err = kstrtoul(buf, 10, &rpm);
+	if (err)
+		return err;
 
 	rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX);
 
@@ -300,7 +304,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct max6650_data *data = i2c_get_clientdata(client);
-	int pwm = simple_strtoul(buf, NULL, 10);
+	unsigned long pwm;
+	int err;
+
+	err = kstrtoul(buf, 10, &pwm);
+	if (err)
+		return err;
 
 	pwm = SENSORS_LIMIT(pwm, 0, 255);
 
@@ -341,14 +350,16 @@ static ssize_t set_enable(struct device *dev, struct device_attribute *devattr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct max6650_data *data = i2c_get_clientdata(client);
-	int mode = simple_strtoul(buf, NULL, 10);
 	int max6650_modes[3] = {0, 3, 2};
+	unsigned long mode;
+	int err;
+
+	err = kstrtoul(buf, 10, &mode);
+	if (err)
+		return err;
 
-	if ((mode < 0)||(mode > 2)) {
-		dev_err(&client->dev,
-			"illegal value for pwm1_enable (%d)\n", mode);
+	if (mode > 2)
 		return -EINVAL;
-	}
 
 	mutex_lock(&data->update_lock);
 
@@ -389,7 +400,12 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct max6650_data *data = i2c_get_clientdata(client);
-	int div = simple_strtoul(buf, NULL, 10);
+	unsigned long div;
+	int err;
+
+	err = kstrtoul(buf, 10, &div);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (div) {
@@ -407,8 +423,6 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
 		break;
 	default:
 		mutex_unlock(&data->update_lock);
-		dev_err(&client->dev,
-			"illegal value for fan divider (%d)\n", div);
 		return -EINVAL;
 	}
 
@@ -529,7 +543,8 @@ static int max6650_probe(struct i2c_client *client,
 	struct max6650_data *data;
 	int err;
 
-	if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL);
+	if (!data) {
 		dev_err(&client->dev, "out of memory.\n");
 		return -ENOMEM;
 	}
@@ -596,49 +611,47 @@ static int max6650_init_client(struct i2c_client *client)
 	}
 
 	switch (fan_voltage) {
-		case 0:
-			break;
-		case 5:
-			config &= ~MAX6650_CFG_V12;
-			break;
-		case 12:
-			config |= MAX6650_CFG_V12;
-			break;
-		default:
-			dev_err(&client->dev,
-				"illegal value for fan_voltage (%d)\n",
-				fan_voltage);
+	case 0:
+		break;
+	case 5:
+		config &= ~MAX6650_CFG_V12;
+		break;
+	case 12:
+		config |= MAX6650_CFG_V12;
+		break;
+	default:
+		dev_err(&client->dev, "illegal value for fan_voltage (%d)\n",
+			fan_voltage);
 	}
 
 	dev_info(&client->dev, "Fan voltage is set to %dV.\n",
 		 (config & MAX6650_CFG_V12) ? 12 : 5);
 
 	switch (prescaler) {
-		case 0:
-			break;
-		case 1:
-			config &= ~MAX6650_CFG_PRESCALER_MASK;
-			break;
-		case 2:
-			config = (config & ~MAX6650_CFG_PRESCALER_MASK)
-				 | MAX6650_CFG_PRESCALER_2;
-			break;
-		case  4:
-			config = (config & ~MAX6650_CFG_PRESCALER_MASK)
-				 | MAX6650_CFG_PRESCALER_4;
-			break;
-		case  8:
-			config = (config & ~MAX6650_CFG_PRESCALER_MASK)
-				 | MAX6650_CFG_PRESCALER_8;
-			break;
-		case 16:
-			config = (config & ~MAX6650_CFG_PRESCALER_MASK)
-				 | MAX6650_CFG_PRESCALER_16;
-			break;
-		default:
-			dev_err(&client->dev,
-				"illegal value for prescaler (%d)\n",
-				prescaler);
+	case 0:
+		break;
+	case 1:
+		config &= ~MAX6650_CFG_PRESCALER_MASK;
+		break;
+	case 2:
+		config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+			 | MAX6650_CFG_PRESCALER_2;
+		break;
+	case  4:
+		config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+			 | MAX6650_CFG_PRESCALER_4;
+		break;
+	case  8:
+		config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+			 | MAX6650_CFG_PRESCALER_8;
+		break;
+	case 16:
+		config = (config & ~MAX6650_CFG_PRESCALER_MASK)
+			 | MAX6650_CFG_PRESCALER_16;
+		break;
+	default:
+		dev_err(&client->dev, "illegal value for prescaler (%d)\n",
+			prescaler);
 	}
 
 	dev_info(&client->dev, "Prescaler is set to %d.\n",
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
index ef65ab5..04d13b3 100644
--- a/drivers/hwmon/mc13783-adc.c
+++ b/drivers/hwmon/mc13783-adc.c
@@ -220,7 +220,7 @@ static int __devexit mc13783_adc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver mc13783_adc_driver = {
-	.remove 	= __devexit_p(mc13783_adc_remove),
+	.remove		= __devexit_p(mc13783_adc_remove),
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= MC13783_ADC_NAME,
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index 3d99b88..51c97ca 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -56,11 +56,11 @@ static u8 confreg[4];
 static int init = 1;
 module_param(init, int, 0);
 MODULE_PARM_DESC(init,
- "Chip initialization level:\n"
- " 0: None\n"
- "*1: Forcibly enable internal voltage and temperature channels, except in9\n"
- " 2: Forcibly enable all voltage and temperature channels, except in9\n"
- " 3: Forcibly enable all voltage and temperature channels, including in9");
+"Chip initialization level:\n"
+" 0: None\n"
+"*1: Forcibly enable internal voltage and temperature channels, except in9\n"
+" 2: Forcibly enable all voltage and temperature channels, except in9\n"
+" 3: Forcibly enable all voltage and temperature channels, including in9");
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
@@ -88,19 +88,19 @@ static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS };
 static inline void superio_outb(int sioaddr, int reg, int val)
 {
 	outb(reg, sioaddr);
-	outb(val, sioaddr+1);
+	outb(val, sioaddr + 1);
 }
 
 static inline int superio_inb(int sioaddr, int reg)
 {
 	outb(reg, sioaddr);
-	return inb(sioaddr+1);
+	return inb(sioaddr + 1);
 }
 
 static inline void superio_exit(int sioaddr)
 {
 	outb(0x02, sioaddr);
-	outb(0x02, sioaddr+1);
+	outb(0x02, sioaddr + 1);
 }
 
 /*
@@ -122,18 +122,18 @@ static inline void superio_exit(int sioaddr)
 #define PC87360_REG_FAN(nr)		(0x07 + 3 * (nr))
 #define PC87360_REG_FAN_STATUS(nr)	(0x08 + 3 * (nr))
 
-#define FAN_FROM_REG(val,div)		((val) == 0 ? 0: \
-					 480000 / ((val)*(div)))
-#define FAN_TO_REG(val,div)		((val) <= 100 ? 0 : \
-					 480000 / ((val)*(div)))
-#define FAN_DIV_FROM_REG(val)		(1 << ((val >> 5) & 0x03))
+#define FAN_FROM_REG(val, div)		((val) == 0 ? 0 : \
+					 480000 / ((val) * (div)))
+#define FAN_TO_REG(val, div)		((val) <= 100 ? 0 : \
+					 480000 / ((val) * (div)))
+#define FAN_DIV_FROM_REG(val)		(1 << (((val) >> 5) & 0x03))
 #define FAN_STATUS_FROM_REG(val)	((val) & 0x07)
 
-#define FAN_CONFIG_MONITOR(val,nr)	(((val) >> (2 + nr * 3)) & 1)
-#define FAN_CONFIG_CONTROL(val,nr)	(((val) >> (3 + nr * 3)) & 1)
-#define FAN_CONFIG_INVERT(val,nr)	(((val) >> (4 + nr * 3)) & 1)
+#define FAN_CONFIG_MONITOR(val, nr)	(((val) >> (2 + (nr) * 3)) & 1)
+#define FAN_CONFIG_CONTROL(val, nr)	(((val) >> (3 + (nr) * 3)) & 1)
+#define FAN_CONFIG_INVERT(val, nr)	(((val) >> (4 + (nr) * 3)) & 1)
 
-#define PWM_FROM_REG(val,inv)		((inv) ? 255 - (val) : (val))
+#define PWM_FROM_REG(val, inv)		((inv) ? 255 - (val) : (val))
 static inline u8 PWM_TO_REG(int val, int inv)
 {
 	if (inv)
@@ -159,10 +159,10 @@ static inline u8 PWM_TO_REG(int val, int inv)
 #define PC87365_REG_IN_ALARMS2		0x01
 #define PC87365_REG_VID			0x06
 
-#define IN_FROM_REG(val,ref)		(((val) * (ref) + 128) / 256)
-#define IN_TO_REG(val,ref)		((val) < 0 ? 0 : \
-					 (val)*256 >= (ref)*255 ? 255: \
-					 ((val) * 256 + (ref)/2) / (ref))
+#define IN_FROM_REG(val, ref)		(((val) * (ref) + 128) / 256)
+#define IN_TO_REG(val, ref)		((val) < 0 ? 0 : \
+					 (val) * 256 >= (ref) * 255 ? 255 : \
+					 ((val) * 256 + (ref) / 2) / (ref))
 
 /*
  * Temperature registers and conversions
@@ -255,43 +255,54 @@ static struct platform_driver pc87360_driver = {
  * Sysfs stuff
  */
 
-static ssize_t show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_fan_input(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index],
 		       FAN_DIV_FROM_REG(data->fan_status[attr->index])));
 }
-static ssize_t show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_fan_min(struct device *dev,
+			    struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index],
 		       FAN_DIV_FROM_REG(data->fan_status[attr->index])));
 }
-static ssize_t show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_fan_div(struct device *dev,
+			    struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n",
 		       FAN_DIV_FROM_REG(data->fan_status[attr->index]));
 }
-static ssize_t show_fan_status(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_fan_status(struct device *dev,
+			       struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n",
 		       FAN_STATUS_FROM_REG(data->fan_status[attr->index]));
 }
-static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, const char *buf,
+static ssize_t set_fan_min(struct device *dev,
+			   struct device_attribute *devattr, const char *buf,
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long fan_min = simple_strtol(buf, NULL, 10);
+	long fan_min;
+	int err;
+
+	err = kstrtol(buf, 10, &fan_min);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	fan_min = FAN_TO_REG(fan_min, FAN_DIV_FROM_REG(data->fan_status[attr->index]));
+	fan_min = FAN_TO_REG(fan_min,
+			     FAN_DIV_FROM_REG(data->fan_status[attr->index]));
 
 	/* If it wouldn't fit, change clock divisor */
 	while (fan_min > 255
@@ -301,11 +312,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr,
 		data->fan_status[attr->index] += 0x20;
 	}
 	data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min;
-	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_MIN(attr->index),
+	pc87360_write_value(data, LD_FAN, NO_BANK,
+			    PC87360_REG_FAN_MIN(attr->index),
 			    data->fan_min[attr->index]);
 
 	/* Write new divider, preserve alarm bits */
-	pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_FAN_STATUS(attr->index),
+	pc87360_write_value(data, LD_FAN, NO_BANK,
+			    PC87360_REG_FAN_STATUS(attr->index),
 			    data->fan_status[attr->index] & 0xF9);
 	mutex_unlock(&data->update_lock);
 
@@ -339,7 +352,8 @@ static struct sensor_device_attribute fan_min[] = {
 	&fan_div[X].dev_attr.attr,	\
 	&fan_min[X].dev_attr.attr
 
-static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
+			char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
@@ -348,12 +362,17 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, ch
 				    FAN_CONFIG_INVERT(data->fan_conf,
 						      attr->index)));
 }
-static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
+		       const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm[attr->index] = PWM_TO_REG(val,
@@ -370,7 +389,7 @@ static struct sensor_device_attribute pwm[] = {
 	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
 };
 
-static struct attribute * pc8736x_fan_attr_array[] = {
+static struct attribute *pc8736x_fan_attr_array[] = {
 	FAN_UNIT_ATTRS(0),
 	FAN_UNIT_ATTRS(1),
 	FAN_UNIT_ATTRS(2),
@@ -383,39 +402,48 @@ static const struct attribute_group pc8736x_fan_group = {
 	.attrs = pc8736x_fan_attr_array,
 };
 
-static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_in_input(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_in_min(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_in_min(struct device *dev,
+			   struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_in_max(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_in_max(struct device *dev,
+			   struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_in_status(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_in_status(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->in_status[attr->index]);
 }
-static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
+			  const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
@@ -424,12 +452,17 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr,
+			  const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[attr->index] = IN_TO_REG(val,
@@ -554,27 +587,38 @@ static struct sensor_device_attribute in_max_alarm[] = {
 	&in_min_alarm[X].dev_attr.attr,	\
 	&in_max_alarm[X].dev_attr.attr
 
-static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+			char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
-static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+			char *buf)
 {
 	struct pc87360_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%u\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
 {
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 
-static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_in_alarms(struct device *dev,
+			      struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->in_alarms);
@@ -602,46 +646,58 @@ static const struct attribute_group pc8736x_vin_group = {
 	.attrs = pc8736x_vin_attr_array,
 };
 
-static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_therm_input(struct device *dev,
+				struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_therm_min(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_therm_min(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_therm_max(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_therm_max(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index],
 		       data->in_vref));
 }
-static ssize_t show_therm_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_therm_crit(struct device *dev,
+			       struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11],
 		       data->in_vref));
 }
-static ssize_t show_therm_status(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_therm_status(struct device *dev,
+				 struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->in_status[attr->index]);
 }
-static ssize_t set_therm_min(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+
+static ssize_t set_therm_min(struct device *dev,
+			     struct device_attribute *devattr,
+			     const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[attr->index] = IN_TO_REG(val, data->in_vref);
@@ -650,12 +706,19 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_therm_max(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+
+static ssize_t set_therm_max(struct device *dev,
+			     struct device_attribute *devattr,
+			     const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[attr->index] = IN_TO_REG(val, data->in_vref);
@@ -664,12 +727,18 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+static ssize_t set_therm_crit(struct device *dev,
+			      struct device_attribute *devattr,
+			      const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref);
@@ -683,38 +752,38 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat
    used in the chip to measure voltage across the thermistors
 */
 static struct sensor_device_attribute therm_input[] = {
-	SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11),
-	SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11),
-	SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11),
+	SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0 + 11),
+	SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1 + 11),
+	SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2 + 11),
 };
 static struct sensor_device_attribute therm_status[] = {
-	SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11),
-	SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11),
-	SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11),
+	SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0 + 11),
+	SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1 + 11),
+	SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2 + 11),
 };
 static struct sensor_device_attribute therm_min[] = {
 	SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR,
-		    show_therm_min, set_therm_min, 0+11),
+		    show_therm_min, set_therm_min, 0 + 11),
 	SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR,
-		    show_therm_min, set_therm_min, 1+11),
+		    show_therm_min, set_therm_min, 1 + 11),
 	SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR,
-		    show_therm_min, set_therm_min, 2+11),
+		    show_therm_min, set_therm_min, 2 + 11),
 };
 static struct sensor_device_attribute therm_max[] = {
 	SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR,
-		    show_therm_max, set_therm_max, 0+11),
+		    show_therm_max, set_therm_max, 0 + 11),
 	SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR,
-		    show_therm_max, set_therm_max, 1+11),
+		    show_therm_max, set_therm_max, 1 + 11),
 	SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR,
-		    show_therm_max, set_therm_max, 2+11),
+		    show_therm_max, set_therm_max, 2 + 11),
 };
 static struct sensor_device_attribute therm_crit[] = {
 	SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
-		    show_therm_crit, set_therm_crit, 0+11),
+		    show_therm_crit, set_therm_crit, 0 + 11),
 	SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR,
-		    show_therm_crit, set_therm_crit, 1+11),
+		    show_therm_crit, set_therm_crit, 1 + 11),
 	SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR,
-		    show_therm_crit, set_therm_crit, 2+11),
+		    show_therm_crit, set_therm_crit, 2 + 11),
 };
 
 /* show_therm_min/max_alarm() reads data from the per-channel voltage
@@ -747,27 +816,27 @@ static ssize_t show_therm_crit_alarm(struct device *dev,
 
 static struct sensor_device_attribute therm_min_alarm[] = {
 	SENSOR_ATTR(temp4_min_alarm, S_IRUGO,
-		    show_therm_min_alarm, NULL, 0+11),
+		    show_therm_min_alarm, NULL, 0 + 11),
 	SENSOR_ATTR(temp5_min_alarm, S_IRUGO,
-		    show_therm_min_alarm, NULL, 1+11),
+		    show_therm_min_alarm, NULL, 1 + 11),
 	SENSOR_ATTR(temp6_min_alarm, S_IRUGO,
-		    show_therm_min_alarm, NULL, 2+11),
+		    show_therm_min_alarm, NULL, 2 + 11),
 };
 static struct sensor_device_attribute therm_max_alarm[] = {
 	SENSOR_ATTR(temp4_max_alarm, S_IRUGO,
-		    show_therm_max_alarm, NULL, 0+11),
+		    show_therm_max_alarm, NULL, 0 + 11),
 	SENSOR_ATTR(temp5_max_alarm, S_IRUGO,
-		    show_therm_max_alarm, NULL, 1+11),
+		    show_therm_max_alarm, NULL, 1 + 11),
 	SENSOR_ATTR(temp6_max_alarm, S_IRUGO,
-		    show_therm_max_alarm, NULL, 2+11),
+		    show_therm_max_alarm, NULL, 2 + 11),
 };
 static struct sensor_device_attribute therm_crit_alarm[] = {
 	SENSOR_ATTR(temp4_crit_alarm, S_IRUGO,
-		    show_therm_crit_alarm, NULL, 0+11),
+		    show_therm_crit_alarm, NULL, 0 + 11),
 	SENSOR_ATTR(temp5_crit_alarm, S_IRUGO,
-		    show_therm_crit_alarm, NULL, 1+11),
+		    show_therm_crit_alarm, NULL, 1 + 11),
 	SENSOR_ATTR(temp6_crit_alarm, S_IRUGO,
-		    show_therm_crit_alarm, NULL, 2+11),
+		    show_therm_crit_alarm, NULL, 2 + 11),
 };
 
 #define THERM_UNIT_ATTRS(X) \
@@ -780,7 +849,7 @@ static struct sensor_device_attribute therm_crit_alarm[] = {
 	&therm_max_alarm[X].dev_attr.attr, \
 	&therm_crit_alarm[X].dev_attr.attr
 
-static struct attribute * pc8736x_therm_attr_array[] = {
+static struct attribute *pc8736x_therm_attr_array[] = {
 	THERM_UNIT_ATTRS(0),
 	THERM_UNIT_ATTRS(1),
 	THERM_UNIT_ATTRS(2),
@@ -790,42 +859,59 @@ static const struct attribute_group pc8736x_therm_group = {
 	.attrs = pc8736x_therm_attr_array,
 };
 
-static ssize_t show_temp_input(struct device *dev, struct device_attribute *devattr, char *buf)
+static ssize_t show_temp_input(struct device *dev,
+			       struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
 }
-static ssize_t show_temp_min(struct device *dev, struct device_attribute *devattr, char *buf)
+
+static ssize_t show_temp_min(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index]));
 }
-static ssize_t show_temp_max(struct device *dev, struct device_attribute *devattr, char *buf)
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index]));
 }
-static ssize_t show_temp_crit(struct device *dev, struct device_attribute *devattr, char *buf)
+
+static ssize_t show_temp_crit(struct device *dev,
+			      struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[attr->index]));
+	return sprintf(buf, "%d\n",
+		       TEMP_FROM_REG(data->temp_crit[attr->index]));
 }
-static ssize_t show_temp_status(struct device *dev, struct device_attribute *devattr, char *buf)
+
+static ssize_t show_temp_status(struct device *dev,
+				struct device_attribute *devattr, char *buf)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_status[attr->index]);
 }
-static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+
+static ssize_t set_temp_min(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[attr->index] = TEMP_TO_REG(val);
@@ -834,12 +920,19 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[attr->index] = TEMP_TO_REG(val);
@@ -848,12 +941,19 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devattr, const char *buf,
-	size_t count)
+
+static ssize_t set_temp_crit(struct device *dev,
+			     struct device_attribute *devattr, const char *buf,
+			     size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct pc87360_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_crit[attr->index] = TEMP_TO_REG(val);
@@ -898,11 +998,13 @@ static struct sensor_device_attribute temp_crit[] = {
 		    show_temp_crit, set_temp_crit, 2),
 };
 
-static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_alarms(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->temp_alarms);
 }
+
 static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
 
 /* show_temp_min/max_alarm() reads data from the per-channel status
@@ -917,6 +1019,7 @@ static ssize_t show_temp_min_alarm(struct device *dev,
 
 	return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN));
 }
+
 static ssize_t show_temp_max_alarm(struct device *dev,
 			struct device_attribute *devattr, char *buf)
 {
@@ -925,6 +1028,7 @@ static ssize_t show_temp_max_alarm(struct device *dev,
 
 	return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX));
 }
+
 static ssize_t show_temp_crit_alarm(struct device *dev,
 			struct device_attribute *devattr, char *buf)
 {
@@ -939,11 +1043,13 @@ static struct sensor_device_attribute temp_min_alarm[] = {
 	SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1),
 	SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2),
 };
+
 static struct sensor_device_attribute temp_max_alarm[] = {
 	SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0),
 	SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1),
 	SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2),
 };
+
 static struct sensor_device_attribute temp_crit_alarm[] = {
 	SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0),
 	SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1),
@@ -976,7 +1082,7 @@ static struct sensor_device_attribute temp_fault[] = {
 	&temp_crit_alarm[X].dev_attr.attr, \
 	&temp_fault[X].dev_attr.attr
 
-static struct attribute * pc8736x_temp_attr_array[] = {
+static struct attribute *pc8736x_temp_attr_array[] = {
 	TEMP_UNIT_ATTRS(0),
 	TEMP_UNIT_ATTRS(1),
 	TEMP_UNIT_ATTRS(2),
@@ -984,6 +1090,7 @@ static struct attribute * pc8736x_temp_attr_array[] = {
 	&dev_attr_alarms_temp.attr,
 	NULL
 };
+
 static const struct attribute_group pc8736x_temp_group = {
 	.attrs = pc8736x_temp_attr_array,
 };
@@ -994,13 +1101,15 @@ static ssize_t show_name(struct device *dev,
 	struct pc87360_data *data = dev_get_drvdata(dev);
 	return sprintf(buf, "%s\n", data->name);
 }
+
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 /*
  * Device detection, registration and update
  */
 
-static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
+static int __init pc87360_find(int sioaddr, u8 *devid,
+			       unsigned short *addresses)
 {
 	u16 val;
 	int i;
@@ -1047,7 +1156,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses
 
 		addresses[i] = val;
 
-		if (i==0) { /* Fans */
+		if (i == 0) { /* Fans */
 			confreg[0] = superio_inb(sioaddr, 0xF0);
 			confreg[1] = superio_inb(sioaddr, 0xF1);
 
@@ -1060,7 +1169,7 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses
 			pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3,
 				 confreg[1] & 1, (confreg[1] >> 1) & 1,
 				 (confreg[1] >> 2) & 1);
-		} else if (i==1) { /* Voltages */
+		} else if (i == 1) { /* Voltages */
 			/* Are we using thermistors? */
 			if (*devid == 0xE9) { /* PC87366 */
 				/* These registers are not logical-device
@@ -1094,7 +1203,8 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
 	int use_thermistors = 0;
 	struct device *dev = &pdev->dev;
 
-	if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
+	data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
 
 	data->fannr = 2;
@@ -1130,9 +1240,10 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, data);
 
 	for (i = 0; i < LDNI_MAX; i++) {
-		if (((data->address[i] = extra_isa[i]))
+		data->address[i] = extra_isa[i];
+		if (data->address[i]
 		 && !request_region(extra_isa[i], PC87360_EXTENT,
-		 		    pc87360_driver.driver.name)) {
+				    pc87360_driver.driver.name)) {
 			dev_err(dev, "Region 0x%x-0x%x already "
 				"in use!\n", extra_isa[i],
 				extra_isa[i]+PC87360_EXTENT-1);
@@ -1182,15 +1293,17 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
 
 	/* Register all-or-nothing sysfs groups */
 
-	if (data->innr &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &pc8736x_vin_group)))
-		goto ERROR3;
+	if (data->innr) {
+		err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group);
+		if (err)
+			goto ERROR3;
+	}
 
-	if (data->innr == 14 &&
-	    (err = sysfs_create_group(&dev->kobj,
-				      &pc8736x_therm_group)))
-		goto ERROR3;
+	if (data->innr == 14) {
+		err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group);
+		if (err)
+			goto ERROR3;
+	}
 
 	/* create device attr-files for varying sysfs groups */
 
@@ -1216,7 +1329,8 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
 					&temp_fault[i].dev_attr)))
 				goto ERROR3;
 		}
-		if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
+		err = device_create_file(dev, &dev_attr_alarms_temp);
+		if (err)
 			goto ERROR3;
 	}
 
@@ -1232,12 +1346,15 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
 					&fan_status[i].dev_attr))))
 			goto ERROR3;
 
-		if (FAN_CONFIG_CONTROL(data->fan_conf, i)
-		    && (err = device_create_file(dev, &pwm[i].dev_attr)))
-			goto ERROR3;
+		if (FAN_CONFIG_CONTROL(data->fan_conf, i)) {
+			err = device_create_file(dev, &pwm[i].dev_attr);
+			if (err)
+				goto ERROR3;
+		}
 	}
 
-	if ((err = device_create_file(dev, &dev_attr_name)))
+	err = device_create_file(dev, &dev_attr_name);
+	if (err)
 		goto ERROR3;
 
 	data->hwmon_dev = hwmon_device_register(dev);
@@ -1255,9 +1372,8 @@ ERROR3:
 	sysfs_remove_group(&dev->kobj, &pc8736x_therm_group);
 	sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
 	for (i = 0; i < 3; i++) {
-		if (data->address[i]) {
+		if (data->address[i])
 			release_region(data->address[i], PC87360_EXTENT);
-		}
 	}
 ERROR1:
 	kfree(data);
@@ -1278,9 +1394,8 @@ static int __devexit pc87360_remove(struct platform_device *pdev)
 	sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group);
 
 	for (i = 0; i < 3; i++) {
-		if (data->address[i]) {
+		if (data->address[i])
 			release_region(data->address[i], PC87360_EXTENT);
-		}
 	}
 	kfree(data);
 
@@ -1375,12 +1490,12 @@ static void pc87360_init_device(struct platform_device *pdev,
 	for (; i < data->tempnr; i++) {
 		reg = pc87360_read_value(data, LD_TEMP, i,
 					 PC87365_REG_TEMP_STATUS);
-		dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i+1, reg);
+		dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i + 1, reg);
 		if (init >= init_temp[i]) {
 			/* Forcibly enable temperature channel */
 			if (!(reg & CHAN_ENA)) {
-				dev_dbg(&pdev->dev, "Forcibly "
-					"enabling temp%d\n", i+1);
+				dev_dbg(&pdev->dev,
+					"Forcibly enabling temp%d\n", i + 1);
 				pc87360_write_value(data, LD_TEMP, i,
 						    PC87365_REG_TEMP_STATUS,
 						    0xCF);
@@ -1394,11 +1509,11 @@ static void pc87360_init_device(struct platform_device *pdev,
 				/* The pin may already be used by thermal
 				   diodes */
 				reg = pc87360_read_value(data, LD_TEMP,
-				      (i-11)/2, PC87365_REG_TEMP_STATUS);
+				      (i - 11) / 2, PC87365_REG_TEMP_STATUS);
 				if (reg & CHAN_ENA) {
-					dev_dbg(&pdev->dev, "Skipping "
-						"temp%d, pin already in use "
-						"by temp%d\n", i-7, (i-11)/2);
+					dev_dbg(&pdev->dev,
+			"Skipping temp%d, pin already in use by temp%d\n",
+						i - 7, (i - 11) / 2);
 					continue;
 				}
 
@@ -1406,8 +1521,9 @@ static void pc87360_init_device(struct platform_device *pdev,
 				reg = pc87360_read_value(data, LD_IN, i,
 							 PC87365_REG_IN_STATUS);
 				if (!(reg & CHAN_ENA)) {
-					dev_dbg(&pdev->dev, "Forcibly "
-						"enabling temp%d\n", i-7);
+					dev_dbg(&pdev->dev,
+						"Forcibly enabling temp%d\n",
+						i - 7);
 					pc87360_write_value(data, LD_IN, i,
 						PC87365_REG_TEMP_STATUS,
 						(reg & 0x60) | 0x8F);
@@ -1421,8 +1537,8 @@ static void pc87360_init_device(struct platform_device *pdev,
 					 PC87365_REG_IN_CONFIG);
 		dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg);
 		if (reg & CHAN_ENA) {
-			dev_dbg(&pdev->dev, "Forcibly "
-				"enabling monitoring (VLM)\n");
+			dev_dbg(&pdev->dev,
+				"Forcibly enabling monitoring (VLM)\n");
 			pc87360_write_value(data, LD_IN, NO_BANK,
 					    PC87365_REG_IN_CONFIG,
 					    reg & 0xFE);
@@ -1434,8 +1550,8 @@ static void pc87360_init_device(struct platform_device *pdev,
 					 PC87365_REG_TEMP_CONFIG);
 		dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg);
 		if (reg & CHAN_ENA) {
-			dev_dbg(&pdev->dev, "Forcibly enabling "
-				"monitoring (TMS)\n");
+			dev_dbg(&pdev->dev,
+				"Forcibly enabling monitoring (TMS)\n");
 			pc87360_write_value(data, LD_TEMP, NO_BANK,
 					    PC87365_REG_TEMP_CONFIG,
 					    reg & 0xFE);
@@ -1470,7 +1586,7 @@ static void pc87360_autodiv(struct device *dev, int nr)
 			data->fan[nr] >>= 1;
 			dev_dbg(dev, "Increasing "
 				"clock divider to %d for fan %d\n",
-				FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1);
+				FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1);
 		}
 	} else {
 		/* Decrease clock divider if possible */
@@ -1483,7 +1599,7 @@ static void pc87360_autodiv(struct device *dev, int nr)
 			dev_dbg(dev, "Decreasing "
 				"clock divider to %d for fan %d\n",
 				FAN_DIV_FROM_REG(data->fan_status[nr]),
-				nr+1);
+				nr + 1);
 		}
 	}
 
diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c
index 731b09a..474c97d 100644
--- a/drivers/hwmon/pcf8591.c
+++ b/drivers/hwmon/pcf8591.c
@@ -68,7 +68,7 @@ MODULE_PARM_DESC(input_mode,
 #define PCF8591_INIT_AOUT	0	/* DAC out = 0 */
 
 /* Conversions */
-#define REG_TO_SIGNED(reg)	(((reg) & 0x80)?((reg) - 256):(reg))
+#define REG_TO_SIGNED(reg)	(((reg) & 0x80) ? ((reg) - 256) : (reg))
 
 struct pcf8591_data {
 	struct device *hwmon_dev;
@@ -83,7 +83,9 @@ static int pcf8591_read_channel(struct device *dev, int channel);
 
 /* following are the sysfs callback functions */
 #define show_in_channel(channel)					\
-static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf)	\
+static ssize_t show_in##channel##_input(struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
 {									\
 	return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
 }									\
@@ -95,39 +97,57 @@ show_in_channel(1);
 show_in_channel(2);
 show_in_channel(3);
 
-static ssize_t show_out0_ouput(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_out0_ouput(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
 	return sprintf(buf, "%d\n", data->aout * 10);
 }
 
-static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_out0_output(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
 {
-	unsigned int value;
+	unsigned long val;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pcf8591_data *data = i2c_get_clientdata(client);
-	if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255) {
-		data->aout = value;
-		i2c_smbus_write_byte_data(client, data->control, data->aout);
-		return count;
-	}
-	return -EINVAL;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	val /= 10;
+	if (val > 255)
+		return -EINVAL;
+
+	data->aout = val;
+	i2c_smbus_write_byte_data(client, data->control, data->aout);
+	return count;
 }
 
 static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO,
 		   show_out0_ouput, set_out0_output);
 
-static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_out0_enable(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
 	return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
 }
 
-static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_out0_enable(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pcf8591_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	if (val)
@@ -174,7 +194,8 @@ static int pcf8591_probe(struct i2c_client *client,
 	struct pcf8591_data *data;
 	int err;
 
-	if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit;
 	}
@@ -192,15 +213,15 @@ static int pcf8591_probe(struct i2c_client *client,
 
 	/* Register input2 if not in "two differential inputs" mode */
 	if (input_mode != 3) {
-		if ((err = device_create_file(&client->dev,
-					      &dev_attr_in2_input)))
+		err = device_create_file(&client->dev, &dev_attr_in2_input);
+		if (err)
 			goto exit_sysfs_remove;
 	}
 
 	/* Register input3 only in "four single ended inputs" mode */
 	if (input_mode == 0) {
-		if ((err = device_create_file(&client->dev,
-					      &dev_attr_in3_input)))
+		err = device_create_file(&client->dev, &dev_attr_in3_input);
+		if (err)
 			goto exit_sysfs_remove;
 	}
 
@@ -269,9 +290,9 @@ static int pcf8591_read_channel(struct device *dev, int channel)
 
 	if ((channel == 2 && input_mode == 2) ||
 	    (channel != 3 && (input_mode == 1 || input_mode == 3)))
-		return (10 * REG_TO_SIGNED(value));
+		return 10 * REG_TO_SIGNED(value);
 	else
-		return (10 * value);
+		return 10 * value;
 }
 
 static const struct i2c_device_id pcf8591_id[] = {
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 00460d8..b31f461 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -781,7 +781,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
 	int ret;
 	u16 regval;
 
-	if (strict_strtol(buf, 10, &val) < 0)
+	if (kstrtol(buf, 10, &val) < 0)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 6ddeae0..46af605 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -806,7 +806,7 @@ static void sht15_bh_read_data(struct work_struct *work_s)
 		 */
 		atomic_set(&data->interrupt_handled, 0);
 		enable_irq(gpio_to_irq(data->pdata->gpio_data));
-		/* If still not occurred or another handler has been scheduled */
+		/* If still not occurred or another handler was scheduled */
 		if (gpio_get_value(data->pdata->gpio_data)
 		    || atomic_read(&data->interrupt_handled))
 			return;
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 47d7ce9..fa0e04e 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -26,7 +26,7 @@
 /*
    SiS southbridge has a LM78-like chip integrated on the same IC.
    This driver is a customized copy of lm78.c
-   
+
    Supports following revisions:
 	Version		PCI ID		PCI Revision
 	1		1039/0008	AF or less
@@ -36,7 +36,7 @@
 	 5595. We recognize these by the presence of the listed
 	 "blacklist" PCI ID and refuse to load.
 
-   NOT SUPPORTED	PCI ID		BLACKLIST PCI ID	
+   NOT SUPPORTED	PCI ID		BLACKLIST PCI ID
 	 540		0008		0540
 	 550		0008		0550
 	5513		0008		5511
@@ -105,11 +105,11 @@ static struct platform_device *pdev;
    OVER and HYST are really MAX and MIN. */
 
 #define REV2MIN	0xb0
-#define SIS5595_REG_TEMP 	(( data->revision) >= REV2MIN) ? \
+#define SIS5595_REG_TEMP	((data->revision) >= REV2MIN) ? \
 					SIS5595_REG_IN(4) : 0x27
-#define SIS5595_REG_TEMP_OVER	(( data->revision) >= REV2MIN) ? \
+#define SIS5595_REG_TEMP_OVER	((data->revision) >= REV2MIN) ? \
 					SIS5595_REG_IN_MAX(4) : 0x39
-#define SIS5595_REG_TEMP_HYST	(( data->revision) >= REV2MIN) ? \
+#define SIS5595_REG_TEMP_HYST	((data->revision) >= REV2MIN) ? \
 					SIS5595_REG_IN_MIN(4) : 0x3a
 
 #define SIS5595_REG_CONFIG 0x40
@@ -138,7 +138,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 
 static inline int FAN_FROM_REG(u8 val, int div)
 {
-	return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
+	return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
 }
 
 /* TEMP: mC (-54.12C to +157.53C)
@@ -150,14 +150,14 @@ static inline int TEMP_FROM_REG(s8 val)
 static inline s8 TEMP_TO_REG(int val)
 {
 	int nval = SENSORS_LIMIT(val, -54120, 157530) ;
-	return nval<0 ? (nval-5212-415)/830 : (nval-5212+415)/830;
+	return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830;
 }
 
 /* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
    REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
 static inline u8 DIV_TO_REG(int val)
 {
-	return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
+	return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1;
 }
 #define DIV_FROM_REG(val) (1 << (val))
 
@@ -240,7 +240,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
 	struct sis5595_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
@@ -255,7 +260,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
 	struct sis5595_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
@@ -279,22 +289,30 @@ show_in_offset(3);
 show_in_offset(4);
 
 /* Temperature */
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
 }
 
-static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
 }
 
-static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct sis5595_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_over = TEMP_TO_REG(val);
@@ -303,16 +321,23 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
 }
 
-static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
 {
 	struct sis5595_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst = TEMP_TO_REG(val);
@@ -335,7 +360,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
-		DIV_FROM_REG(data->fan_div[nr])) );
+		DIV_FROM_REG(data->fan_div[nr])));
 }
 
 static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
@@ -344,8 +369,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
 	struct sis5595_data *data = sis5595_update_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
-		DIV_FROM_REG(data->fan_div[nr])) );
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+		DIV_FROM_REG(data->fan_div[nr])));
 }
 
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
@@ -354,7 +379,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
 	struct sis5595_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -369,7 +399,7 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
 	struct sis5595_data *data = sis5595_update_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
 
 /* Note: we save and restore the fan minimum here, because its value is
@@ -383,8 +413,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
 	unsigned long min;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
@@ -392,17 +427,25 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 	reg = sis5595_read_value(data, SIS5595_REG_FANDIV);
 
 	switch (val) {
-	case 1: data->fan_div[nr] = 0; break;
-	case 2: data->fan_div[nr] = 1; break;
-	case 4: data->fan_div[nr] = 2; break;
-	case 8: data->fan_div[nr] = 3; break;
+	case 1:
+		data->fan_div[nr] = 0;
+		break;
+	case 2:
+		data->fan_div[nr] = 1;
+		break;
+	case 4:
+		data->fan_div[nr] = 2;
+		break;
+	case 8:
+		data->fan_div[nr] = 3;
+		break;
 	default:
 		dev_err(dev, "fan_div value %ld not "
 			"supported. Choose one of 1, 2, 4 or 8!\n", val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
-	
+
 	switch (nr) {
 	case 0:
 		reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
@@ -431,7 +474,8 @@ show_fan_offset(1);
 show_fan_offset(2);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
@@ -521,7 +565,7 @@ static struct attribute *sis5595_attributes_temp1[] = {
 static const struct attribute_group sis5595_group_temp1 = {
 	.attrs = sis5595_attributes_temp1,
 };
- 
+
 /* This is called when the module is loaded */
 static int __devinit sis5595_probe(struct platform_device *pdev)
 {
@@ -539,7 +583,8 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
 		goto exit;
 	}
 
-	if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
@@ -550,7 +595,9 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
 	data->name = "sis5595";
 	platform_set_drvdata(pdev, data);
 
-	/* Check revision and pin registers to determine whether 4 or 5 voltages */
+	/*
+	 * Check revision and pin registers to determine whether 4 or 5 voltages
+	 */
 	data->revision = s_bridge->revision;
 	/* 4 voltages, 1 temp */
 	data->maxins = 3;
@@ -560,7 +607,7 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
 			/* 5 voltages, no temps */
 			data->maxins = 4;
 	}
-	
+
 	/* Initialize the SIS5595 chip */
 	sis5595_init_device(data);
 
@@ -571,15 +618,16 @@ static int __devinit sis5595_probe(struct platform_device *pdev)
 	}
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
+	err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group);
+	if (err)
 		goto exit_free;
 	if (data->maxins == 4) {
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &sis5595_group_in4)))
+		err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_in4);
+		if (err)
 			goto exit_remove_files;
 	} else {
-		if ((err = sysfs_create_group(&pdev->dev.kobj,
-					      &sis5595_group_temp1)))
+		err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_temp1);
+		if (err)
 			goto exit_remove_files;
 	}
 
@@ -699,7 +747,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
 	return data;
 }
 
-static const struct pci_device_id sis5595_pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
 	{ 0, }
 };
@@ -770,13 +818,16 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
 
 	for (i = blacklist; *i != 0; i++) {
 		struct pci_dev *d;
-		if ((d = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL))) {
-			dev_err(&d->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
+		d = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
+		if (d) {
+			dev_err(&d->dev,
+				"Looked for SIS5595 but found unsupported device %.4x\n",
+				*i);
 			pci_dev_put(d);
 			return -ENODEV;
 		}
 	}
-	
+
 	force_addr &= ~(SIS5595_EXTENT - 1);
 	if (force_addr) {
 		dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr);
@@ -788,10 +839,11 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
 		dev_err(&dev->dev, "Failed to read ISA address\n");
 		return -ENODEV;
 	}
-	
+
 	address &= ~(SIS5595_EXTENT - 1);
 	if (!address) {
-		dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
+		dev_err(&dev->dev,
+			"Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
 	if (force_addr && address != force_addr) {
diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c
index 4116381..1b4301f 100644
--- a/drivers/hwmon/smm665.c
+++ b/drivers/hwmon/smm665.c
@@ -376,7 +376,7 @@ static ssize_t smm665_show_input(struct device *dev,
 }
 
 #define SMM665_SHOW(what) \
-  static ssize_t smm665_show_##what(struct device *dev, \
+static ssize_t smm665_show_##what(struct device *dev, \
 				    struct device_attribute *da, char *buf) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index f44a89a..43a0032 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -1,6 +1,6 @@
 /*
     smsc47m1.c - Part of lm_sensors, Linux kernel modules
-                 for hardware monitoring
+		for hardware monitoring
 
     Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x,
     LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997
@@ -9,7 +9,7 @@
     Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
     Copyright (C) 2004-2007 Jean Delvare <khali@linux-fr.org>
     Ported to Linux 2.6 by Gabriele Gorla <gorlik@yahoo.com>
-                        and Jean Delvare
+			and Jean Delvare
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -111,10 +111,11 @@ static const u8 SMSC47M1_REG_PWM[3]		= { 0x56, 0x57, 0x69 };
 #define SMSC47M2_REG_PPIN3		0x2c
 #define SMSC47M2_REG_FANDIV3		0x6a
 
-#define MIN_FROM_REG(reg,div)		((reg)>=192 ? 0 : \
-					 983040/((192-(reg))*(div)))
-#define FAN_FROM_REG(reg,div,preload)	((reg)<=(preload) || (reg)==255 ? 0 : \
-					 983040/(((reg)-(preload))*(div)))
+#define MIN_FROM_REG(reg, div)		((reg) >= 192 ? 0 : \
+					 983040 / ((192 - (reg)) * (div)))
+#define FAN_FROM_REG(reg, div, preload)	((reg) <= (preload) || (reg) == 255 ? \
+					 0 : \
+					 983040 / (((reg) - (preload)) * (div)))
 #define DIV_FROM_REG(reg)		(1 << (reg))
 #define PWM_FROM_REG(reg)		(((reg) & 0x7E) << 1)
 #define PWM_EN_FROM_REG(reg)		((~(reg)) & 0x01)
@@ -238,7 +239,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct smsc47m1_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	long rpmdiv, val = simple_strtol(buf, NULL, 10);
+	long rpmdiv;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
@@ -266,18 +273,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct smsc47m1_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	long new_div = simple_strtol(buf, NULL, 10), tmp;
+	long new_div;
+	int err;
+	long tmp;
 	u8 old_div = DIV_FROM_REG(data->fan_div[nr]);
 
+	err = kstrtol(buf, 10, &new_div);
+	if (err)
+		return err;
+
 	if (new_div == old_div) /* No change */
 		return count;
 
 	mutex_lock(&data->update_lock);
 	switch (new_div) {
-	case 1: data->fan_div[nr] = 0; break;
-	case 2: data->fan_div[nr] = 1; break;
-	case 4: data->fan_div[nr] = 2; break;
-	case 8: data->fan_div[nr] = 3; break;
+	case 1:
+		data->fan_div[nr] = 0;
+		break;
+	case 2:
+		data->fan_div[nr] = 1;
+		break;
+	case 4:
+		data->fan_div[nr] = 2;
+		break;
+	case 8:
+		data->fan_div[nr] = 3;
+		break;
 	default:
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -315,7 +336,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct smsc47m1_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (val < 0 || val > 255)
 		return -EINVAL;
@@ -336,9 +362,14 @@ static ssize_t set_pwm_en(struct device *dev, struct device_attribute
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct smsc47m1_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	long val = simple_strtol(buf, NULL, 10);
-	
-	if (val != 0 && val != 1)
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (val > 1)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -592,7 +623,7 @@ static int __init smsc47m1_probe(struct platform_device *pdev)
 	int err;
 	int fan1, fan2, fan3, pwm1, pwm2, pwm3;
 
-	static const char *names[] = {
+	static const char * const names[] = {
 		"smsc47m1",
 		"smsc47m2",
 	};
@@ -603,7 +634,8 @@ static int __init smsc47m1_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
-	if (!(data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto error_release;
 	}
@@ -718,9 +750,11 @@ static int __init smsc47m1_probe(struct platform_device *pdev)
 	} else if (data->type == smsc47m2)
 		dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
 
-	if ((err = device_create_file(dev, &dev_attr_alarms)))
+	err = device_create_file(dev, &dev_attr_alarms);
+	if (err)
 		goto error_remove_files;
-	if ((err = device_create_file(dev, &dev_attr_name)))
+	err = device_create_file(dev, &dev_attr_name);
+	if (err)
 		goto error_remove_files;
 
 	data->hwmon_dev = hwmon_device_register(dev);
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index 40b2667..95761bd 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -1,6 +1,6 @@
 /*
     smsc47m192.c - Support for hardware monitoring block of
-                   SMSC LPC47M192 and compatible Super I/O chips
+		SMSC LPC47M192 and compatible Super I/O chips
 
     Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
 
@@ -37,16 +37,16 @@
 static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
 
 /* SMSC47M192 registers */
-#define SMSC47M192_REG_IN(nr)		((nr)<6 ? (0x20 + (nr)) : \
+#define SMSC47M192_REG_IN(nr)		((nr) < 6 ? (0x20 + (nr)) : \
 					(0x50 + (nr) - 6))
-#define SMSC47M192_REG_IN_MAX(nr)	((nr)<6 ? (0x2b + (nr) * 2) : \
+#define SMSC47M192_REG_IN_MAX(nr)	((nr) < 6 ? (0x2b + (nr) * 2) : \
 					(0x54 + (((nr) - 6) * 2)))
-#define SMSC47M192_REG_IN_MIN(nr)	((nr)<6 ? (0x2c + (nr) * 2) : \
+#define SMSC47M192_REG_IN_MIN(nr)	((nr) < 6 ? (0x2c + (nr) * 2) : \
 					(0x55 + (((nr) - 6) * 2)))
 static u8 SMSC47M192_REG_TEMP[3] =	{ 0x27, 0x26, 0x52 };
 static u8 SMSC47M192_REG_TEMP_MAX[3] =	{ 0x39, 0x37, 0x58 };
 static u8 SMSC47M192_REG_TEMP_MIN[3] =	{ 0x3A, 0x38, 0x59 };
-#define SMSC47M192_REG_TEMP_OFFSET(nr)	((nr)==2 ? 0x1e : 0x1f)
+#define SMSC47M192_REG_TEMP_OFFSET(nr)	((nr) == 2 ? 0x1e : 0x1f)
 #define SMSC47M192_REG_ALARM1		0x41
 #define SMSC47M192_REG_ALARM2		0x42
 #define SMSC47M192_REG_VID		0x47
@@ -170,7 +170,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val, nr);
@@ -187,7 +192,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val, nr);
@@ -249,7 +259,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = TEMP_TO_REG(val);
@@ -266,7 +281,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = TEMP_TO_REG(val);
@@ -293,22 +313,27 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute
 	struct i2c_client *client = to_i2c_client(dev);
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_offset[nr] = TEMP_TO_REG(val);
-	if (nr>1)
+	if (nr > 1)
 		i2c_smbus_write_byte_data(client,
 			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
 	else if (data->temp_offset[nr] != 0) {
 		/* offset[0] and offset[1] share the same register,
 			SFR bit 4 activates offset[0] */
 		i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
-					(sfr & 0xef) | (nr==0 ? 0x10 : 0));
+					(sfr & 0xef) | (nr == 0 ? 0x10 : 0));
 		data->temp_offset[1-nr] = 0;
 		i2c_smbus_write_byte_data(client,
 			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
-	} else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0))
+	} else if ((sfr & 0x10) == (nr == 0 ? 0x10 : 0))
 		i2c_smbus_write_byte_data(client,
 					SMSC47M192_REG_TEMP_OFFSET(nr), 0);
 	mutex_unlock(&data->update_lock);
@@ -349,7 +374,14 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct smsc47m192_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
@@ -458,13 +490,13 @@ static void smsc47m192_init_client(struct i2c_client *client)
 						(sfr & 0xfd) | 0x02);
 	if (!(config & 0x01)) {
 		/* initialize alarm limits */
-		for (i=0; i<8; i++) {
+		for (i = 0; i < 8; i++) {
 			i2c_smbus_write_byte_data(client,
 				SMSC47M192_REG_IN_MIN(i), 0);
 			i2c_smbus_write_byte_data(client,
 				SMSC47M192_REG_IN_MAX(i), 0xff);
 		}
-		for (i=0; i<3; i++) {
+		for (i = 0; i < 3; i++) {
 			i2c_smbus_write_byte_data(client,
 				SMSC47M192_REG_TEMP_MIN[i], 0x80);
 			i2c_smbus_write_byte_data(client,
@@ -532,14 +564,16 @@ static int smsc47m192_probe(struct i2c_client *client,
 	smsc47m192_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group)))
+	err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group);
+	if (err)
 		goto exit_free;
 
 	/* Pin 110 is either in4 (+12V) or VID4 */
 	config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
 	if (!(config & 0x20)) {
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					      &smsc47m192_group_in4)))
+		err = sysfs_create_group(&client->dev.kobj,
+					 &smsc47m192_group_in4);
+		if (err)
 			goto exit_remove_files;
 	}
 
@@ -624,7 +658,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
 		data->alarms = i2c_smbus_read_byte_data(client,
 						SMSC47M192_REG_ALARM1) |
 			       (i2c_smbus_read_byte_data(client,
-		       				SMSC47M192_REG_ALARM2) << 8);
+						SMSC47M192_REG_ALARM2) << 8);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
index 7dfb4de..a195914 100644
--- a/drivers/hwmon/thmc50.c
+++ b/drivers/hwmon/thmc50.c
@@ -1,6 +1,6 @@
 /*
     thmc50.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
+	monitoring
     Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl>
     Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and
     Philip Edelbrock <phil@netroedge.com>
@@ -124,8 +124,13 @@ static ssize_t set_analog_out(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct thmc50_data *data = i2c_get_clientdata(client);
-	int tmp = simple_strtoul(buf, NULL, 10);
 	int config;
+	unsigned long tmp;
+	int err;
+
+	err = kstrtoul(buf, 10, &tmp);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->analog_out = SENSORS_LIMIT(tmp, 0, 255);
@@ -173,7 +178,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct thmc50_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
@@ -197,7 +207,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct thmc50_data *data = i2c_get_clientdata(client);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
@@ -360,14 +375,16 @@ static int thmc50_probe(struct i2c_client *client,
 	thmc50_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group)))
+	err = sysfs_create_group(&client->dev.kobj, &thmc50_group);
+	if (err)
 		goto exit_free;
 
 	/* Register ADM1022 sysfs hooks */
-	if (data->has_temp3)
-		if ((err = sysfs_create_group(&client->dev.kobj,
-					      &temp3_group)))
+	if (data->has_temp3) {
+		err = sysfs_create_group(&client->dev.kobj, &temp3_group);
+		if (err)
 			goto exit_remove_sysfs_thmc50;
+	}
 
 	/* Register a new directory entry with module sensors */
 	data->hwmon_dev = hwmon_device_register(&client->dev);
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index b9a87e8..836de7e 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -90,7 +90,8 @@ static void env_write(struct env *p, u8 ireg, u8 val)
 #define FAN_PERIOD_INVALID	(0xff << 8)
 #define FAN_DATA_VALID(x)	((x) && (x) != FAN_PERIOD_INVALID)
 
-static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	int fan_nr = to_sensor_dev_attr(attr)->index;
 	struct env *p = dev_get_drvdata(dev);
@@ -111,10 +112,15 @@ static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
 	int fan_nr = to_sensor_dev_attr(attr)->index;
-	int rpm = simple_strtol(buf, NULL, 10);
+	unsigned long rpm;
 	struct env *p = dev_get_drvdata(dev);
 	int period;
 	u8 val;
+	int err;
+
+	err = kstrtoul(buf, 10, &rpm);
+	if (err)
+		return err;
 
 	if (!rpm)
 		return -EINVAL;
@@ -126,7 +132,8 @@ static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr,
+			      char *buf)
 {
 	int fan_nr = to_sensor_dev_attr(attr)->index;
 	struct env *p = dev_get_drvdata(dev);
@@ -148,7 +155,8 @@ fan(4);
 
 static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6);
 
-static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	int temp_nr = to_sensor_dev_attr(attr)->index;
 	struct env *p = dev_get_drvdata(dev);
@@ -168,7 +176,8 @@ static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6);
 static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7);
 static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13);
 
-static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr,
+			     char *buf)
 {
 	int index = to_sensor_dev_attr(attr)->index;
 	struct env *p = dev_get_drvdata(dev);
@@ -181,9 +190,11 @@ static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr,
 static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0);
 static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1);
 static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2);
-static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, 3);
+static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL,
+			  3);
 
-static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_fwver(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct env *p = dev_get_drvdata(dev);
 	u8 val;
@@ -194,7 +205,8 @@ static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, cha
 
 static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0);
 
-static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
 {
 	return sprintf(buf, "ultra45\n");
 }
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 25e9166..c759b1c 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -166,7 +166,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255);
 }
 
-#define FAN_FROM_REG(val,div) ((val)==0?0:(val)==255?0:1350000/((val)*(div)))
+#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (val) == 255 ? 0 : 1350000 / \
+				((val) * (div)))
 
 /******** TEMP CONVERSIONS (Bob Dougherty) *********/
 /* linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
@@ -200,8 +201,8 @@ static inline u8 FAN_TO_REG(long rpm, int div)
  but the function is very linear in the useful range (0-80 deg C), so
  we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
  is the temp at via register values 0-255: */
-static const s16 tempLUT[] =
-{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+static const s16 tempLUT[] = {
+	-709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
 	-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
 	-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
 	-255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
@@ -246,8 +247,8 @@ static const s16 tempLUT[] =
  viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
  - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
  Note that n=161: */
-static const u8 viaLUT[] =
-{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+static const u8 viaLUT[] = {
+	12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
 	23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
 	41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
 	69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
@@ -290,7 +291,7 @@ static inline long TEMP_FROM_REG10(u16 val)
 }
 
 #define DIV_FROM_REG(val) (1 << (val))
-#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
+#define DIV_TO_REG(val) ((val) == 8 ? 3 : (val) == 4 ? 2 : (val) == 1 ? 0 : 1)
 
 /* For each registered chip, we need to keep some data in memory.
    The structure is dynamically allocated. */
@@ -365,7 +366,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val, nr);
@@ -379,7 +385,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val, nr);
@@ -429,7 +440,12 @@ static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_over[nr] = TEMP_TO_REG(val);
@@ -443,7 +459,12 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst[nr] = TEMP_TO_REG(val);
@@ -471,7 +492,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
-				DIV_FROM_REG(data->fan_div[nr])) );
+				DIV_FROM_REG(data->fan_div[nr])));
 }
 static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
 		char *buf) {
@@ -479,21 +500,27 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
 	return sprintf(buf, "%d\n",
-		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
+		FAN_FROM_REG(data->fan_min[nr],
+			     DIV_FROM_REG(data->fan_div[nr])));
 }
 static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
 		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
 		const char *buf, size_t count) {
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	int val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -506,8 +533,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
 	struct via686a_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	int nr = attr->index;
-	int val = simple_strtol(buf, NULL, 10);
 	int old;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	old = via686a_read_value(data, VIA686A_REG_FANDIV);
@@ -530,10 +562,13 @@ show_fan_offset(1);
 show_fan_offset(2);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
 	struct via686a_data *data = via686a_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
 }
+
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
@@ -641,7 +676,8 @@ static int __devinit via686a_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
@@ -655,7 +691,8 @@ static int __devinit via686a_probe(struct platform_device *pdev)
 	via686a_init_device(data);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group)))
+	err = sysfs_create_group(&pdev->dev.kobj, &via686a_group);
+	if (err)
 		goto exit_free;
 
 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
@@ -777,11 +814,10 @@ static struct via686a_data *via686a_update_device(struct device *dev)
 	return data;
 }
 
-static const struct pci_device_id via686a_pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
-	{ 0, }
+	{ }
 };
-
 MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 
 static int __devinit via686a_device_add(unsigned short address)
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index 49163d4..7ca0ebe 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -377,7 +377,12 @@ static ssize_t set_in(struct device *dev, struct device_attribute *attr,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -446,7 +451,12 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (fn) {
@@ -517,8 +527,13 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
 	int reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -536,16 +551,23 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
 		break;
 	case SHOW_SET_FAN_DIV:
 		switch (val) {
-			case 1: data->fan_div[ix] = 0; break;
-			case 2: data->fan_div[ix] = 1; break;
-			case 4: data->fan_div[ix] = 2; break;
-			case 8: data->fan_div[ix] = 3; break;
-			default:
-				count = -EINVAL;
-				dev_warn(dev, "fan div value %ld not "
-					 "supported. Choose one of 1, 2, "
-					 "4, or 8.\n", val);
-				goto EXIT;
+		case 1:
+			data->fan_div[ix] = 0;
+			break;
+		case 2:
+			data->fan_div[ix] = 1;
+			break;
+		case 4:
+			data->fan_div[ix] = 2;
+			break;
+		case 8:
+			data->fan_div[ix] = 3;
+			break;
+		default:
+			count = -EINVAL;
+			dev_warn(dev, "fan div value %ld not supported. "
+				 "Choose one of 1, 2, 4, or 8.\n", val);
+			goto EXIT;
 		}
 		vt1211_write8(data, VT1211_REG_FAN_DIV,
 			      ((data->fan_div[1] << 6) |
@@ -610,8 +632,13 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int fn = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
 	int tmp, reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -630,9 +657,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 			data->pwm_ctl[ix] &= 7;
 			/* disable SmartGuardian if both PWM outputs are
 			 * disabled */
-			if ((data->pwm_ctl[ix ^ 1] & 1) == 0) {
+			if ((data->pwm_ctl[ix ^ 1] & 1) == 0)
 				data->fan_ctl &= 0xe;
-			}
 			break;
 		case 2:
 			data->pwm_ctl[ix] |= 8;
@@ -656,16 +682,15 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 		val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000);
 		/* calculate tmp = log2(val) */
 		tmp = 0;
-		for (val >>= 1; val > 0; val >>= 1) {
+		for (val >>= 1; val > 0; val >>= 1)
 			tmp++;
-		}
 		/* sync the data cache */
 		reg = vt1211_read8(data, VT1211_REG_PWM_CLK);
 		data->pwm_clk = (reg & 0xf8) | tmp;
 		vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk);
 		break;
 	case SHOW_SET_PWM_AUTO_CHANNELS_TEMP:
-		if ((val < 1) || (val > 7)) {
+		if (val < 1 || val > 7) {
 			count = -EINVAL;
 			dev_warn(dev, "temp channel %ld not supported. "
 				 "Choose a value between 1 and 7.\n", val);
@@ -741,8 +766,14 @@ static ssize_t set_pwm_auto_point_temp(struct device *dev,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int ap = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
 	int reg;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
+
 
 	mutex_lock(&data->update_lock);
 
@@ -798,16 +829,15 @@ static ssize_t set_pwm_auto_point_pwm(struct device *dev,
 						to_sensor_dev_attr_2(attr);
 	int ix = sensor_attr_2->index;
 	int ap = sensor_attr_2->nr;
-	long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
 
-	if ((val < 0) || (val > 255)) {
-		dev_err(dev, "pwm value %ld is out of range. "
-			"Choose a value between 0 and 255.\n" , val);
-		return -EINVAL;
-	}
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	data->pwm_auto_pwm[ix][ap] = val;
+	data->pwm_auto_pwm[ix][ap] = SENSORS_LIMIT(val, 0, 255);
 	vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap),
 		      data->pwm_auto_pwm[ix][ap]);
 	mutex_unlock(&data->update_lock);
@@ -831,9 +861,14 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
 		       const char *buf, size_t count)
 {
 	struct vt1211_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	unsigned long val;
+	int err;
 
-	data->vrm = val;
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 
 	return count;
 }
@@ -1119,9 +1154,8 @@ static void vt1211_remove_sysfs(struct platform_device *pdev)
 		device_remove_file(dev,
 			&vt1211_sysfs_fan_pwm[i].dev_attr);
 	}
-	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
+	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++)
 		device_remove_file(dev, &vt1211_sysfs_misc[i]);
-	}
 }
 
 static int __devinit vt1211_probe(struct platform_device *pdev)
@@ -1131,7 +1165,8 @@ static int __devinit vt1211_probe(struct platform_device *pdev)
 	struct resource *res;
 	int i, err;
 
-	if (!(data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		dev_err(dev, "Out of memory\n");
 		goto EXIT;
@@ -1185,16 +1220,14 @@ static int __devinit vt1211_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) {
 		err = device_create_file(dev,
 			&vt1211_sysfs_fan_pwm[i].dev_attr);
-		if (err) {
+		if (err)
 			goto EXIT_DEV_REMOVE;
-		}
 	}
 	for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) {
 		err = device_create_file(dev,
 		       &vt1211_sysfs_misc[i]);
-		if (err) {
+		if (err)
 			goto EXIT_DEV_REMOVE;
-		}
 	}
 
 	/* Register device */
@@ -1293,9 +1326,8 @@ static int __init vt1211_find(int sio_cip, unsigned short *address)
 	superio_enter(sio_cip);
 
 	devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID);
-	if (devid != SIO_VT1211_ID) {
+	if (devid != SIO_VT1211_ID)
 		goto EXIT;
-	}
 
 	superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
 
@@ -1325,35 +1357,35 @@ static int __init vt1211_init(void)
 	int err;
 	unsigned short address = 0;
 
-	if ((err = vt1211_find(SIO_REG_CIP1, &address)) &&
-	    (err = vt1211_find(SIO_REG_CIP2, &address))) {
-		goto EXIT;
+	err = vt1211_find(SIO_REG_CIP1, &address);
+	if (err) {
+		err = vt1211_find(SIO_REG_CIP2, &address);
+		if (err)
+			goto EXIT;
 	}
 
 	if ((uch_config < -1) || (uch_config > 31)) {
 		err = -EINVAL;
 		pr_warn("Invalid UCH configuration %d. "
 			"Choose a value between 0 and 31.\n", uch_config);
-	  goto EXIT;
+		goto EXIT;
 	}
 
 	if ((int_mode < -1) || (int_mode > 0)) {
 		err = -EINVAL;
 		pr_warn("Invalid interrupt mode %d. "
 			"Only mode 0 is supported.\n", int_mode);
-	  goto EXIT;
+		goto EXIT;
 	}
 
 	err = platform_driver_register(&vt1211_driver);
-	if (err) {
+	if (err)
 		goto EXIT;
-	}
 
 	/* Sets global pdev as a side effect */
 	err = vt1211_device_add(address);
-	if (err) {
+	if (err)
 		goto EXIT_DRV_UNREGISTER;
-	}
 
 	return 0;
 
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index db3b2e8..eb74f37 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -56,12 +56,12 @@ static struct platform_device *pdev;
    which sets the selected inputs marked with '*' below if multiple options are
    possible:
 
-	            Voltage Mode	  Temperature Mode
-	Sensor	      Linux Id	      Linux Id        VIA Id
-	--------      --------	      --------        ------
+		    Voltage Mode	  Temperature Mode
+	Sensor	      Linux Id	      Linux Id	      VIA Id
+	--------      --------	      --------	      ------
 	CPU Diode	N/A		temp1		0
 	UIC1		in0		temp2 *		1
-	UIC2		in1 *		temp3   	2
+	UIC2		in1 *		temp3		2
 	UIC3		in2 *		temp4		3
 	UIC4		in3 *		temp5		4
 	UIC5		in4 *		temp6		5
@@ -222,7 +222,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
@@ -237,7 +242,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
@@ -278,7 +288,12 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
@@ -292,7 +307,12 @@ static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
@@ -346,7 +366,12 @@ static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
@@ -358,7 +383,12 @@ static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
@@ -400,7 +430,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
@@ -414,7 +449,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	int val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
@@ -436,7 +476,8 @@ static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,	\
 
 static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL);
 static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max);
-static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, set_temp0_min);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min,
+		   set_temp0_min);
 
 define_temperature_sysfs(2);
 define_temperature_sysfs(3);
@@ -480,7 +521,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct vt8231_data *data = dev_get_drvdata(dev);
-	int val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -494,21 +540,34 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 {
 	struct vt8231_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
 	int nr = sensor_attr->index;
 	int old = vt8231_read_value(data, VT8231_REG_FANDIV);
 	long min = FAN_FROM_REG(data->fan_min[nr],
 				 DIV_FROM_REG(data->fan_div[nr]));
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	switch (val) {
-	case 1: data->fan_div[nr] = 0; break;
-	case 2: data->fan_div[nr] = 1; break;
-	case 4: data->fan_div[nr] = 2; break;
-	case 8: data->fan_div[nr] = 3; break;
+	case 1:
+		data->fan_div[nr] = 0;
+		break;
+	case 2:
+		data->fan_div[nr] = 1;
+		break;
+	case 4:
+		data->fan_div[nr] = 2;
+		break;
+	case 8:
+		data->fan_div[nr] = 3;
+		break;
 	default:
 		dev_err(dev, "fan_div value %ld not supported. "
-		        "Choose one of 1, 2, 4 or 8!\n", val);
+			"Choose one of 1, 2, 4 or 8!\n", val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
@@ -699,7 +758,7 @@ static struct platform_driver vt8231_driver = {
 	.remove	= __devexit_p(vt8231_remove),
 };
 
-static const struct pci_device_id vt8231_pci_ids[] = {
+static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) },
 	{ 0, }
 };
@@ -707,7 +766,7 @@ static const struct pci_device_id vt8231_pci_ids[] = {
 MODULE_DEVICE_TABLE(pci, vt8231_pci_ids);
 
 static int __devinit vt8231_pci_probe(struct pci_dev *dev,
-			 	      const struct pci_device_id *id);
+				      const struct pci_device_id *id);
 
 static struct pci_driver vt8231_pci_driver = {
 	.name		= "vt8231",
@@ -730,7 +789,8 @@ static int vt8231_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	if (!(data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
@@ -743,7 +803,8 @@ static int vt8231_probe(struct platform_device *pdev)
 	vt8231_init_device(data);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group)))
+	err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group);
+	if (err)
 		goto exit_free;
 
 	/* Must update device information to find out the config field */
@@ -751,16 +812,18 @@ static int vt8231_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) {
 		if (ISTEMP(i, data->uch_config)) {
-			if ((err = sysfs_create_group(&pdev->dev.kobj,
-					&vt8231_group_temps[i])))
+			err = sysfs_create_group(&pdev->dev.kobj,
+						 &vt8231_group_temps[i]);
+			if (err)
 				goto exit_remove_files;
 		}
 	}
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) {
 		if (ISVOLT(i, data->uch_config)) {
-			if ((err = sysfs_create_group(&pdev->dev.kobj,
-					&vt8231_group_volts[i])))
+			err = sysfs_create_group(&pdev->dev.kobj,
+						 &vt8231_group_volts[i]);
+			if (err)
 				goto exit_remove_files;
 		}
 	}
@@ -866,17 +929,15 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
 			(vt8231_read_value(data, VT8231_REG_ALARM2) << 8);
 
 		/* Set alarm flags correctly */
-		if (!data->fan[0] && data->fan_min[0]) {
+		if (!data->fan[0] && data->fan_min[0])
 			data->alarms |= 0x40;
-		} else if (data->fan[0] && !data->fan_min[0]) {
+		else if (data->fan[0] && !data->fan_min[0])
 			data->alarms &= ~0x40;
-		}
 
-		if (!data->fan[1] && data->fan_min[1]) {
+		if (!data->fan[1] && data->fan_min[1])
 			data->alarms |= 0x80;
-		} else if (data->fan[1] && !data->fan_min[1]) {
+		else if (data->fan[1] && !data->fan_min[1])
 			data->alarms &= ~0x80;
-		}
 
 		data->last_updated = jiffies;
 		data->valid = 1;
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 374118f..3162309 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -313,7 +313,7 @@ static inline unsigned long pwm_freq_from_reg(u8 reg)
 	/* This should not happen but anyway... */
 	if (reg == 0)
 		reg++;
-	return (clock / (reg << 8));
+	return clock / (reg << 8);
 }
 static inline u8 pwm_freq_to_reg(unsigned long val)
 {
@@ -321,11 +321,11 @@ static inline u8 pwm_freq_to_reg(unsigned long val)
 	if (val >= 93750)	/* The highest we can do */
 		return 0x01;
 	if (val >= 720)	/* Use 24 MHz clock */
-		return (24000000UL / (val << 8));
+		return 24000000UL / (val << 8);
 	if (val < 6)		/* The lowest we can do */
 		return 0xFF;
 	else			/* Use 180 kHz clock */
-		return (0x80 | (180000UL / (val << 8)));
+		return 0x80 | (180000UL / (val << 8));
 }
 
 #define BEEP_MASK_FROM_REG(val)		((val) & 0xff7fff)
@@ -342,7 +342,7 @@ static inline u8 DIV_TO_REG(long val)
 			break;
 		val >>= 1;
 	}
-	return ((u8) i);
+	return (u8)i;
 }
 
 /* For each registered chip, we need to keep some data in memory.
@@ -427,7 +427,12 @@ store_in_min(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
@@ -441,7 +446,12 @@ store_in_max(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
@@ -506,9 +516,12 @@ static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *a
 	const char *buf, size_t count)
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	
@@ -533,9 +546,12 @@ static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *a
 	const char *buf, size_t count)
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -584,7 +600,12 @@ store_fan_min(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -645,9 +666,15 @@ store_temp_max(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
-	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
+	u16 tmp;
+	long val;
+	int err;
 
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
+
+	tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = tmp;
 	w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp);
@@ -661,9 +688,15 @@ store_temp_max_hyst(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	long val = simple_strtol(buf, NULL, 10);
-	u16 tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
+	u16 tmp;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
+	tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val);
 	mutex_lock(&data->update_lock);
 	data->temp_max_hyst[nr] = tmp;
 	w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp);
@@ -701,10 +734,13 @@ static ssize_t
 store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
-	data->vrm = val;
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 
 	return count;
 }
@@ -755,8 +791,11 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
 	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -791,10 +830,14 @@ store_beep(struct device *dev, struct device_attribute *attr,
 {
 	struct w83627hf_data *data = dev_get_drvdata(dev);
 	int bitnr = to_sensor_dev_attr(attr)->index;
-	unsigned long bit;
 	u8 reg;
+	unsigned long bit;
+	int err;
+
+	err = kstrtoul(buf, 10, &bit);
+	if (err)
+		return err;
 
-	bit = simple_strtoul(buf, NULL, 10);
 	if (bit & ~1)
 		return -EINVAL;
 
@@ -884,7 +927,12 @@ store_fan_div(struct device *dev, struct device_attribute *devattr,
 	struct w83627hf_data *data = dev_get_drvdata(dev);
 	unsigned long min;
 	u8 reg;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -933,7 +981,12 @@ store_pwm(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -974,10 +1027,15 @@ store_pwm_enable(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	u8 reg;
+	unsigned long val;
+	int err;
 
-	if (!val || (val > 3))	/* modes 1, 2 and 3 are supported */
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (!val || val > 3)	/* modes 1, 2 and 3 are supported */
 		return -EINVAL;
 	mutex_lock(&data->update_lock);
 	data->pwm_enable[nr] = val;
@@ -1016,9 +1074,12 @@ store_pwm_freq(struct device *dev, struct device_attribute *devattr,
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
 	static const u8 mask[]={0xF8, 0x8F};
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -1060,9 +1121,13 @@ store_temp_type(struct device *dev, struct device_attribute *devattr,
 {
 	int nr = to_sensor_dev_attr(devattr)->index;
 	struct w83627hf_data *data = dev_get_drvdata(dev);
-	u32 val, tmp;
+	unsigned long val;
+	u32 tmp;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -1290,7 +1355,8 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 		goto ERROR0;
 	}
 
-	if (!(data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
@@ -1311,7 +1377,8 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 	w83627hf_update_fan_div(data);
 
 	/* Register common device attributes */
-	if ((err = sysfs_create_group(&dev->kobj, &w83627hf_group)))
+	err = sysfs_create_group(&dev->kobj, &w83627hf_group);
+	if (err)
 		goto ERROR3;
 
 	/* Register chip-specific device attributes */
@@ -1387,10 +1454,11 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 	}
 
 	if (data->type == w83627thf || data->type == w83637hf
-	 || data->type == w83687thf)
-		if ((err = device_create_file(dev,
-				&sensor_dev_attr_pwm3.dev_attr)))
+	    || data->type == w83687thf) {
+		err = device_create_file(dev, &sensor_dev_attr_pwm3.dev_attr);
+		if (err)
 			goto ERROR4;
+	}
 
 	if (data->type == w83637hf || data->type == w83687thf)
 		if ((err = device_create_file(dev,
@@ -1409,10 +1477,12 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 			goto ERROR4;
 
 	if (data->type == w83627thf || data->type == w83637hf
-	 || data->type == w83687thf)
-		if ((err = device_create_file(dev,
-				&sensor_dev_attr_pwm3_enable.dev_attr)))
+	    || data->type == w83687thf) {
+		err = device_create_file(dev,
+					 &sensor_dev_attr_pwm3_enable.dev_attr);
+		if (err)
 			goto ERROR4;
+	}
 
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index 17a8fa2..e8a1900 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -1,9 +1,9 @@
 /*
     w83781d.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
+		monitoring
     Copyright (c) 1998 - 2001  Frodo Looijaard <frodol@dds.nl>,
-                               Philip Edelbrock <phil@netroedge.com>,
-                               and Mark Studebaker <mdsxyz123@yahoo.com>
+			       Philip Edelbrock <phil@netroedge.com>,
+			       and Mark Studebaker <mdsxyz123@yahoo.com>
     Copyright (c) 2007 - 2008  Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
@@ -182,9 +182,9 @@ FAN_FROM_REG(u8 val, int div)
 #define TEMP_TO_REG(val)		SENSORS_LIMIT((val) / 1000, -127, 128)
 #define TEMP_FROM_REG(val)		((val) * 1000)
 
-#define BEEP_MASK_FROM_REG(val,type)	((type) == as99127f ? \
+#define BEEP_MASK_FROM_REG(val, type)	((type) == as99127f ? \
 					 (~(val)) & 0x7fff : (val) & 0xff7fff)
-#define BEEP_MASK_TO_REG(val,type)	((type) == as99127f ? \
+#define BEEP_MASK_TO_REG(val, type)	((type) == as99127f ? \
 					 (~(val)) & 0x7fff : (val) & 0xff7fff)
 
 #define DIV_FROM_REG(val)		(1 << (val))
@@ -254,7 +254,7 @@ static void w83781d_init_device(struct device *dev);
 
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \
 		char *buf) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
@@ -267,20 +267,21 @@ show_in_reg(in_min);
 show_in_reg(in_max);
 
 #define store_in_reg(REG, reg) \
-static ssize_t store_in_##reg (struct device *dev, struct device_attribute \
+static ssize_t store_in_##reg(struct device *dev, struct device_attribute \
 		*da, const char *buf, size_t count) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
 	struct w83781d_data *data = dev_get_drvdata(dev); \
 	int nr = attr->index; \
-	u32 val; \
-	 \
-	val = simple_strtoul(buf, NULL, 10); \
-	 \
+	unsigned long val; \
+	int err = kstrtoul(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = IN_TO_REG(val); \
-	w83781d_write_value(data, W83781D_REG_IN_##REG(nr), data->in_##reg[nr]); \
-	 \
+	w83781d_write_value(data, W83781D_REG_IN_##REG(nr), \
+			    data->in_##reg[nr]); \
+	\
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -306,12 +307,12 @@ sysfs_in_offsets(7);
 sysfs_in_offsets(8);
 
 #define show_fan_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \
 		char *buf) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
 	struct w83781d_data *data = w83781d_update_device(dev); \
-	return sprintf(buf,"%ld\n", \
+	return sprintf(buf, "%ld\n", \
 		FAN_FROM_REG(data->reg[attr->index], \
 			DIV_FROM_REG(data->fan_div[attr->index]))); \
 }
@@ -325,9 +326,12 @@ store_fan_min(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct w83781d_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] =
@@ -350,17 +354,17 @@ static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR,
 		show_fan_min, store_fan_min, 2);
 
 #define show_temp_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \
 		char *buf) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
 	struct w83781d_data *data = w83781d_update_device(dev); \
 	int nr = attr->index; \
 	if (nr >= 2) {	/* TEMP2 and TEMP3 */ \
-		return sprintf(buf,"%d\n", \
+		return sprintf(buf, "%d\n", \
 			LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \
 	} else {	/* TEMP1 */ \
-		return sprintf(buf,"%ld\n", (long)TEMP_FROM_REG(data->reg)); \
+		return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->reg)); \
 	} \
 }
 show_temp_reg(temp);
@@ -368,16 +372,16 @@ show_temp_reg(temp_max);
 show_temp_reg(temp_max_hyst);
 
 #define store_temp_reg(REG, reg) \
-static ssize_t store_temp_##reg (struct device *dev, \
+static ssize_t store_temp_##reg(struct device *dev, \
 		struct device_attribute *da, const char *buf, size_t count) \
 { \
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \
 	struct w83781d_data *data = dev_get_drvdata(dev); \
 	int nr = attr->index; \
 	long val; \
-	 \
-	val = simple_strtol(buf, NULL, 10); \
-	 \
+	int err = kstrtol(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	 \
 	if (nr >= 2) {	/* TEMP2 and TEMP3 */ \
@@ -425,13 +429,17 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static ssize_t
-store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+store_vrm_reg(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
 {
 	struct w83781d_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
-	data->vrm = val;
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 
 	return count;
 }
@@ -480,7 +488,8 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4);
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0);
 
-static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_beep_mask(struct device *dev,
+			       struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
 	return sprintf(buf, "%ld\n",
@@ -492,9 +501,12 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
 	struct w83781d_data *data = dev_get_drvdata(dev);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->beep_mask &= 0x8000; /* preserve beep enable */
@@ -529,10 +541,14 @@ store_beep(struct device *dev, struct device_attribute *attr,
 {
 	struct w83781d_data *data = dev_get_drvdata(dev);
 	int bitnr = to_sensor_dev_attr(attr)->index;
-	unsigned long bit;
 	u8 reg;
+	unsigned long bit;
+	int err;
+
+	err = kstrtoul(buf, 10, &bit);
+	if (err)
+		return err;
 
-	bit = simple_strtoul(buf, NULL, 10);
 	if (bit & ~1)
 		return -EINVAL;
 
@@ -633,7 +649,12 @@ store_fan_div(struct device *dev, struct device_attribute *da,
 	unsigned long min;
 	int nr = attr->index;
 	u8 reg;
-	unsigned long val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -643,10 +664,12 @@ store_fan_div(struct device *dev, struct device_attribute *da,
 
 	data->fan_div[nr] = DIV_TO_REG(val, data->type);
 
-	reg = (w83781d_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
-	       & (nr==0 ? 0xcf : 0x3f))
-	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
-	w83781d_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
+	reg = (w83781d_read_value(data, nr == 2 ?
+				  W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
+		& (nr == 0 ? 0xcf : 0x3f))
+	      | ((data->fan_div[nr] & 0x03) << (nr == 0 ? 4 : 6));
+	w83781d_write_value(data, nr == 2 ?
+			    W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
 
 	/* w83781d and as99127f don't have extended divisor bits */
 	if (data->type != w83781d && data->type != as99127f) {
@@ -693,9 +716,12 @@ store_pwm(struct device *dev, struct device_attribute *da, const char *buf,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct w83781d_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = SENSORS_LIMIT(val, 0, 255);
@@ -709,9 +735,13 @@ store_pwm2_enable(struct device *dev, struct device_attribute *da,
 		const char *buf, size_t count)
 {
 	struct w83781d_data *data = dev_get_drvdata(dev);
-	u32 val, reg;
+	unsigned long val;
+	u32 reg;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -761,9 +791,13 @@ store_sensor(struct device *dev, struct device_attribute *da,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct w83781d_data *data = dev_get_drvdata(dev);
 	int nr = attr->index;
-	u32 val, tmp;
+	unsigned long val;
+	u32 tmp;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -911,7 +945,7 @@ ERROR_SC_1:
 	&sensor_dev_attr_temp##X##_alarm.dev_attr.attr,		\
 	&sensor_dev_attr_temp##X##_beep.dev_attr.attr
 
-static struct attribute* w83781d_attributes[] = {
+static struct attribute *w83781d_attributes[] = {
 	IN_UNIT_ATTRS(0),
 	IN_UNIT_ATTRS(2),
 	IN_UNIT_ATTRS(3),
@@ -959,7 +993,8 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
 {
 	int err;
 
-	if ((err = sysfs_create_group(&dev->kobj, &w83781d_group)))
+	err = sysfs_create_group(&dev->kobj, &w83781d_group);
+	if (err)
 		return err;
 
 	if (kind != w83783s) {
@@ -1043,8 +1078,9 @@ w83781d_create_files(struct device *dev, int kind, int is_isa)
 				&sensor_dev_attr_temp2_type.dev_attr)))
 			return err;
 		if (kind != w83783s) {
-			if ((err = device_create_file(dev,
-					&sensor_dev_attr_temp3_type.dev_attr)))
+			err = device_create_file(dev,
+				&sensor_dev_attr_temp3_type.dev_attr);
+			if (err)
 				return err;
 		}
 	}
@@ -1083,7 +1119,7 @@ w83781d_detect(struct i2c_client *client, struct i2c_board_info *info)
 	/* Check for Winbond or Asus ID if in bank 0 */
 	if (!(val1 & 0x07) &&
 	    ((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) ||
-	     ( (val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) {
+	     ((val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) {
 		dev_dbg(&adapter->dev,
 			"Detection of w83781d chip failed at step 4\n");
 		goto err_nodev;
@@ -1091,7 +1127,7 @@ w83781d_detect(struct i2c_client *client, struct i2c_board_info *info)
 	/* If Winbond SMBus, check address at 0x48.
 	   Asus doesn't support, except for as99127f rev.2 */
 	if ((!(val1 & 0x80) && val2 == 0xa3) ||
-	    ( (val1 & 0x80) && val2 == 0x5c)) {
+	    ((val1 & 0x80) && val2 == 0x5c)) {
 		if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR)
 		    != address) {
 			dev_dbg(&adapter->dev,
@@ -1331,9 +1367,11 @@ w83781d_init_device(struct device *dev)
 		   This saves FAN 1/2/3 input/output values set by BIOS. */
 		w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80);
 		w83781d_write_value(data, W83781D_REG_PWMCLK12, p);
-		/* Disable master beep-enable (reset turns it on).
-		   Individual beep_mask should be reset to off but for some reason
-		   disabling this bit helps some people not get beeped */
+		/*
+		 * Disable master beep-enable (reset turns it on).
+		 * Individual beep_mask should be reset to off but for some
+		 * reason disabling this bit helps some people not get beeped
+		 */
 		w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0);
 	}
 
@@ -1444,7 +1482,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
 			}
 			/* Only PWM2 can be disabled */
 			data->pwm2_enable = (w83781d_read_value(data,
-					      W83781D_REG_PWMCLK12) & 0x08) >> 3;
+					     W83781D_REG_PWMCLK12) & 0x08) >> 3;
 		}
 
 		data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1));
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 35aa514..679146d 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -1,6 +1,6 @@
 /*
     w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
+		monitoring
 
     Copyright (C) 2006-2007 Charles Spirakis <bezaur@gmail.com>
 
@@ -226,7 +226,7 @@ static u8 fan_to_reg(long rpm, int div)
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
-#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+#define FAN_FROM_REG(val, div)	((val) == 0 ? -1 : \
 				((val) == 255 ? 0 : \
 					1350000 / ((val) * (div))))
 
@@ -366,7 +366,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 						to_sensor_dev_attr(attr); \
 	struct w83791d_data *data = w83791d_update_device(dev); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
 }
 
 show_in_reg(in);
@@ -382,9 +382,11 @@ static ssize_t store_in_##reg(struct device *dev, \
 						to_sensor_dev_attr(attr); \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct w83791d_data *data = i2c_get_clientdata(client); \
-	unsigned long val = simple_strtoul(buf, NULL, 10); \
 	int nr = sensor_attr->index; \
-	 \
+	unsigned long val; \
+	int err = kstrtoul(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = IN_TO_REG(val); \
 	w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \
@@ -455,7 +457,14 @@ static ssize_t store_beep(struct device *dev, struct device_attribute *attr,
 	struct w83791d_data *data = i2c_get_clientdata(client);
 	int bitnr = sensor_attr->index;
 	int bytenr = bitnr / 8;
-	long val = simple_strtol(buf, NULL, 10) ? 1 : 0;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	val = val ? 1 : 0;
 
 	mutex_lock(&data->update_lock);
 
@@ -521,7 +530,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 						to_sensor_dev_attr(attr); \
 	struct w83791d_data *data = w83791d_update_device(dev); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf,"%d\n", \
+	return sprintf(buf, "%d\n", \
 		FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
 }
 
@@ -534,8 +543,13 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
-	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int nr = sensor_attr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -572,12 +586,18 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
 	int indx = 0;
 	u8 keep_mask = 0;
 	u8 new_shift = 0;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	/* Save fan_min */
 	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
 
 	mutex_lock(&data->update_lock);
-	data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10));
+	data->fan_div[nr] = div_to_reg(nr, val);
 
 	switch (nr) {
 	case 0:
@@ -918,8 +938,13 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr,
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
 	int nr = attr->index;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp1[nr] = TEMP1_TO_REG(val);
@@ -946,10 +971,15 @@ static ssize_t store_temp23(struct device *dev,
 	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
 	int nr = attr->nr;
 	int index = attr->index;
 
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
+
 	mutex_lock(&data->update_lock);
 	data->temp_add[nr][index] = TEMP23_TO_REG(val);
 	w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2],
@@ -1035,8 +1065,13 @@ static ssize_t store_beep_mask(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
 	int i;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -1063,7 +1098,12 @@ static ssize_t store_beep_enable(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
-	long val = simple_strtol(buf, NULL, 10);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 
@@ -1113,36 +1153,42 @@ static ssize_t store_vrm_reg(struct device *dev,
 				const char *buf, size_t count)
 {
 	struct w83791d_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int err;
 
 	/* No lock needed as vrm is internal to the driver
 	   (not read from a chip register) and so is not
 	   updated in w83791d_update_device() */
-	data->vrm = simple_strtoul(buf, NULL, 10);
 
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
 #define IN_UNIT_ATTRS(X) \
-	&sda_in_input[X].dev_attr.attr, \
-	&sda_in_min[X].dev_attr.attr,   \
-	&sda_in_max[X].dev_attr.attr,   \
-	&sda_in_beep[X].dev_attr.attr,  \
+	&sda_in_input[X].dev_attr.attr,	\
+	&sda_in_min[X].dev_attr.attr,	\
+	&sda_in_max[X].dev_attr.attr,	\
+	&sda_in_beep[X].dev_attr.attr,	\
 	&sda_in_alarm[X].dev_attr.attr
 
 #define FAN_UNIT_ATTRS(X) \
-	&sda_fan_input[X].dev_attr.attr,        \
-	&sda_fan_min[X].dev_attr.attr,          \
-	&sda_fan_div[X].dev_attr.attr,          \
-	&sda_fan_beep[X].dev_attr.attr,         \
+	&sda_fan_input[X].dev_attr.attr,	\
+	&sda_fan_min[X].dev_attr.attr,		\
+	&sda_fan_div[X].dev_attr.attr,		\
+	&sda_fan_beep[X].dev_attr.attr,		\
 	&sda_fan_alarm[X].dev_attr.attr
 
 #define TEMP_UNIT_ATTRS(X) \
-	&sda_temp_input[X].dev_attr.attr,       \
-	&sda_temp_max[X].dev_attr.attr,         \
-	&sda_temp_max_hyst[X].dev_attr.attr,    \
-	&sda_temp_beep[X].dev_attr.attr,        \
+	&sda_temp_input[X].dev_attr.attr,	\
+	&sda_temp_max[X].dev_attr.attr,		\
+	&sda_temp_max_hyst[X].dev_attr.attr,	\
+	&sda_temp_beep[X].dev_attr.attr,	\
 	&sda_temp_alarm[X].dev_attr.attr
 
 static struct attribute *w83791d_attributes[] = {
@@ -1228,9 +1274,8 @@ static int w83791d_detect_subclients(struct i2c_client *client)
 	}
 
 	val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
-	if (!(val & 0x08)) {
+	if (!(val & 0x08))
 		data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
-	}
 	if (!(val & 0x80)) {
 		if ((data->lm75[0] != NULL) &&
 				((val & 0x7) == ((val >> 4) & 0x7))) {
@@ -1265,9 +1310,8 @@ static int w83791d_detect(struct i2c_client *client,
 	int val1, val2;
 	unsigned short address = client->addr;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
-	}
 
 	if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80)
 		return -ENODEV;
@@ -1277,7 +1321,7 @@ static int w83791d_detect(struct i2c_client *client,
 	/* Check for Winbond ID if in bank 0 */
 	if (!(val1 & 0x07)) {
 		if ((!(val1 & 0x80) && val2 != 0xa3) ||
-		    ( (val1 & 0x80) && val2 != 0x5c)) {
+		    ((val1 & 0x80) && val2 != 0x5c)) {
 			return -ENODEV;
 		}
 	}
@@ -1334,12 +1378,12 @@ static int w83791d_probe(struct i2c_client *client,
 
 	/* If the fan_div is changed, make sure there is a rational
 	   fan_min in place */
-	for (i = 0; i < NUMBER_OF_FANIN; i++) {
+	for (i = 0; i < NUMBER_OF_FANIN; i++)
 		data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]);
-	}
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &w83791d_group)))
+	err = sysfs_create_group(&client->dev.kobj, &w83791d_group);
+	if (err)
 		goto error3;
 
 	/* Check if pins of fan/pwm 4-5 are in use as GPIO */
@@ -1604,9 +1648,8 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev)
 	/* temperature math is signed, but only print out the
 	   bits that matter */
 	dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN);
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < 3; i++)
 		dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]);
-	}
 	for (i = 0; i < 2; i++) {
 		for (j = 0; j < 3; j++) {
 			dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j,
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index d3100ea..e356618 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -1,9 +1,9 @@
 /*
     w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
+		monitoring
     Copyright (C) 2004, 2005 Winbond Electronics Corp.
-                        Chunhao Huang <DZShen@Winbond.com.tw>,
-                        Rudolf Marek <r.marek@assembler.cz>
+			Chunhao Huang <DZShen@Winbond.com.tw>,
+			Rudolf Marek <r.marek@assembler.cz>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -222,10 +222,10 @@ static const u8 W83792D_REG_LEVELS[3][4] = {
    variants. Note that you should be a bit careful with which arguments
    these macros are called: arguments may be evaluated more than once.
    Fixing this is just not worth it. */
-#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
-				((((nr)==6)||((nr)==7))?(val*6):(val*4)))
-#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
-				((((nr)==6)||((nr)==7))?(val/6):(val/4)))
+#define IN_FROM_REG(nr, val) (((nr) <= 1) ? ((val) * 2) : \
+		((((nr) == 6) || ((nr) == 7)) ? ((val) * 6) : ((val) * 4)))
+#define IN_TO_REG(nr, val) (((nr) <= 1) ? ((val) / 2) : \
+		((((nr) == 6) || ((nr) == 7)) ? ((val) / 6) : ((val) / 4)))
 
 static inline u8
 FAN_TO_REG(long rpm, int div)
@@ -236,7 +236,7 @@ FAN_TO_REG(long rpm, int div)
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
-#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+#define FAN_FROM_REG(val, div)	((val) == 0   ? -1 : \
 				((val) == 255 ? 0 : \
 						1350000 / ((val) * (div))))
 
@@ -265,7 +265,7 @@ DIV_TO_REG(long val)
 			break;
 		val >>= 1;
 	}
-	return ((u8) i);
+	return (u8)i;
 }
 
 struct w83792d_data {
@@ -333,7 +333,7 @@ static struct i2c_driver w83792d_driver = {
 static inline long in_count_from_reg(int nr, struct w83792d_data *data)
 {
 	/* in7 and in8 do not have low bits, but the formula still works */
-	return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
+	return (data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03);
 }
 
 /* The SMBus locks itself. The Winbond W83792D chip has a bank register,
@@ -357,37 +357,43 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
-	return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
+	return sprintf(buf, "%ld\n",
+		       IN_FROM_REG(nr, in_count_from_reg(nr, data)));
 }
 
 #define show_in_reg(reg) \
 static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 			char *buf) \
 { \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr \
+		= to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	struct w83792d_data *data = w83792d_update_device(dev); \
-	return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \
+	return sprintf(buf, "%ld\n", \
+		       (long)(IN_FROM_REG(nr, data->reg[nr]) * 4)); \
 }
 
 show_in_reg(in_min);
 show_in_reg(in_max);
 
 #define store_in_reg(REG, reg) \
-static ssize_t store_in_##reg (struct device *dev, \
+static ssize_t store_in_##reg(struct device *dev, \
 				struct device_attribute *attr, \
 				const char *buf, size_t count) \
 { \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr \
+			= to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct w83792d_data *data = i2c_get_clientdata(client); \
-	u32 val; \
-	 \
-	val = simple_strtoul(buf, NULL, 10); \
+	unsigned long val; \
+	int err = kstrtoul(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
-	data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
-	w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+	data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val) / 4, 0, 255); \
+	w83792d_write_value(client, W83792D_REG_IN_##REG[nr], \
+			    data->in_##reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	 \
 	return count; \
@@ -396,13 +402,14 @@ store_in_reg(MIN, min);
 store_in_reg(MAX, max);
 
 #define show_fan_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 			char *buf) \
 { \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr \
+			= to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index - 1; \
 	struct w83792d_data *data = w83792d_update_device(dev); \
-	return sprintf(buf,"%d\n", \
+	return sprintf(buf, "%d\n", \
 		FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
 }
 
@@ -417,9 +424,13 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
 	w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
@@ -455,13 +466,19 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
 	/*u8 reg;*/
 	u8 fan_div_reg = 0;
 	u8 tmp_fan_div;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	/* Save fan_min */
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
 			   DIV_FROM_REG(data->fan_div[nr]));
 
-	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+	data->fan_div[nr] = DIV_TO_REG(val);
 
 	fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
 	fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8;
@@ -496,9 +513,13 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	s32 val;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtol(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->temp1[nr] = TEMP1_TO_REG(val);
 	w83792d_write_value(client, W83792D_REG_TEMP1[nr],
@@ -513,11 +534,12 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
 static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
 				char *buf)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
-	return sprintf(buf,"%ld\n",
+	return sprintf(buf, "%ld\n",
 		(long)TEMP_ADD_FROM_REG(data->temp_add[nr][index],
 			data->temp_add[nr][index+1]));
 }
@@ -525,14 +547,19 @@ static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
 static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	s32 val;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtol(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
 	data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
@@ -604,7 +631,13 @@ store_pwm(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	val = SENSORS_LIMIT(val, 0, 255) >> 4;
 
 	mutex_lock(&data->update_lock);
 	val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0;
@@ -623,10 +656,14 @@ store_pwmenable(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
 	u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	if (val < 1 || val > 3)
 		return -EINVAL;
 
@@ -645,7 +682,7 @@ store_pwmenable(struct device *dev, struct device_attribute *attr,
 	cfg1_tmp = data->pwmenable[0];
 	cfg2_tmp = (data->pwmenable[1]) << 2;
 	cfg3_tmp = (data->pwmenable[2]) << 4;
-	cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
+	cfg4_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG) & 0xc0;
 	fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
 	w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
 	mutex_unlock(&data->update_lock);
@@ -671,10 +708,13 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
-	if (val != 0 && val != 1)
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	if (val > 1)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -721,16 +761,20 @@ store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
+	unsigned long val;
+	int err;
 	u8 temp1 = 0, temp2 = 0;
 
 	dev_warn(dev,
 		 "Attribute %s is deprecated, use intrusion0_alarm instead\n",
 		 "chassis_clear");
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
 	mutex_lock(&data->update_lock);
-	data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
+	data->chassis_clear = SENSORS_LIMIT(val, 0, 1);
 	temp1 = ((data->chassis_clear) << 7) & 0x80;
 	temp2 = w83792d_read_value(client,
 		W83792D_REG_CHASSIS_CLR) & 0x7f;
@@ -780,14 +824,19 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
-	u8 target_tmp=0, target_mask=0;
+	u8 target_tmp = 0, target_mask = 0;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	target_tmp = val;
 	target_tmp = target_tmp & 0x7f;
 	mutex_lock(&data->update_lock);
-	target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
+	target_mask = w83792d_read_value(client,
+					 W83792D_REG_THERMAL[nr]) & 0x80;
 	data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
 	w83792d_write_value(client, W83792D_REG_THERMAL[nr],
 		(data->thermal_cruise[nr]) | target_mask);
@@ -815,19 +864,22 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
 	u8 tol_tmp, tol_mask;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	tol_mask = w83792d_read_value(client,
 		W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
 	tol_tmp = SENSORS_LIMIT(val, 0, 15);
 	tol_tmp &= 0x0f;
 	data->tolerance[nr] = tol_tmp;
-	if (nr == 1) {
+	if (nr == 1)
 		tol_tmp <<= 4;
-	}
 	w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
 		tol_mask | tol_tmp);
 	mutex_unlock(&data->update_lock);
@@ -840,7 +892,8 @@ static ssize_t
 show_sf2_point(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
@@ -851,15 +904,20 @@ static ssize_t
 store_sf2_point(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr - 1;
 	int index = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
 	u8 mask_tmp = 0;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
 	mask_tmp = w83792d_read_value(client,
@@ -875,7 +933,8 @@ static ssize_t
 show_sf2_level(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
@@ -887,25 +946,30 @@ static ssize_t
 store_sf2_level(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+	struct sensor_device_attribute_2 *sensor_attr
+	  = to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index - 1;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
-	u8 mask_tmp=0, level_tmp=0;
+	u8 mask_tmp = 0, level_tmp = 0;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
 	mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
-		& ((nr==3) ? 0xf0 : 0x0f);
-	if (nr==3) {
+		& ((nr == 3) ? 0xf0 : 0x0f);
+	if (nr == 3)
 		level_tmp = data->sf2_levels[index][nr];
-	} else {
+	else
 		level_tmp = data->sf2_levels[index][nr] << 4;
-	}
-	w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+	w83792d_write_value(client, W83792D_REG_LEVELS[index][nr],
+			    level_tmp | mask_tmp);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -939,9 +1003,8 @@ w83792d_detect_subclients(struct i2c_client *new_client)
 	}
 
 	val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
-	if (!(val & 0x08)) {
+	if (!(val & 0x08))
 		data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7));
-	}
 	if (!(val & 0x80)) {
 		if ((data->lm75[0] != NULL) &&
 			((val & 0x7) == ((val >> 4) & 0x7))) {
@@ -1306,9 +1369,8 @@ w83792d_detect(struct i2c_client *client, struct i2c_board_info *info)
 	int val1, val2;
 	unsigned short address = client->addr;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
-	}
 
 	if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80)
 		return -ENODEV;
@@ -1318,7 +1380,7 @@ w83792d_detect(struct i2c_client *client, struct i2c_board_info *info)
 	/* Check for Winbond ID if in bank 0 */
 	if (!(val1 & 0x07)) {  /* is Bank0 */
 		if ((!(val1 & 0x80) && val2 != 0xa3) ||
-		    ( (val1 & 0x80) && val2 != 0x5c))
+		    ((val1 & 0x80) && val2 != 0x5c))
 			return -ENODEV;
 	}
 	/* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
@@ -1374,33 +1436,38 @@ w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&dev->kobj, &w83792d_group)))
+	err = sysfs_create_group(&dev->kobj, &w83792d_group);
+	if (err)
 		goto ERROR3;
 
 	/* Read GPIO enable register to check if pins for fan 4,5 are used as
 	   GPIO */
 	val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN);
 
-	if (!(val1 & 0x40))
-		if ((err = sysfs_create_group(&dev->kobj,
-					      &w83792d_group_fan[0])))
+	if (!(val1 & 0x40)) {
+		err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[0]);
+		if (err)
 			goto exit_remove_files;
+	}
 
-	if (!(val1 & 0x20))
-		if ((err = sysfs_create_group(&dev->kobj,
-					      &w83792d_group_fan[1])))
+	if (!(val1 & 0x20)) {
+		err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[1]);
+		if (err)
 			goto exit_remove_files;
+	}
 
 	val1 = w83792d_read_value(client, W83792D_REG_PIN);
-	if (val1 & 0x40)
-		if ((err = sysfs_create_group(&dev->kobj,
-					      &w83792d_group_fan[2])))
+	if (val1 & 0x40) {
+		err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[2]);
+		if (err)
 			goto exit_remove_files;
+	}
 
-	if (val1 & 0x04)
-		if ((err = sysfs_create_group(&dev->kobj,
-					      &w83792d_group_fan[3])))
+	if (val1 & 0x04) {
+		err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[3]);
+		if (err)
 			goto exit_remove_files;
+	}
 
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -1451,9 +1518,9 @@ w83792d_init_client(struct i2c_client *client)
 {
 	u8 temp2_cfg, temp3_cfg, vid_in_b;
 
-	if (init) {
+	if (init)
 		w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
-	}
+
 	/* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
 	   W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
 	     vin0/vin1 can be modified by user;
@@ -1527,7 +1594,7 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 		for (i = 0; i < 2; i++) {
 			for (j = 0; j < 6; j++) {
 				data->temp_add[i][j] = w83792d_read_value(
-					client,W83792D_REG_TEMP_ADD[i][j]);
+					client, W83792D_REG_TEMP_ADD[i][j]);
 			}
 		}
 
@@ -1572,8 +1639,9 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 		/* Update Smart Fan II temperature points */
 		for (i = 0; i < 3; i++) {
 			for (j = 0; j < 4; j++) {
-				data->sf2_points[i][j] = w83792d_read_value(
-					client,W83792D_REG_POINTS[i][j]) & 0x7f;
+				data->sf2_points[i][j]
+				  = w83792d_read_value(client,
+					W83792D_REG_POINTS[i][j]) & 0x7f;
 			}
 		}
 
@@ -1605,10 +1673,10 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 #ifdef DEBUG
 static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
 {
-	int i=0, j=0;
+	int i = 0, j = 0;
 	dev_dbg(dev, "==========The following is the debug message...========\n");
 	dev_dbg(dev, "9 set of Voltages: =====>\n");
-	for (i=0; i<9; i++) {
+	for (i = 0; i < 9; i++) {
 		dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]);
 		dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
 		dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
@@ -1616,27 +1684,26 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
 	dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff);
 	dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8);
 	dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
-	for (i=0; i<7; i++) {
+	for (i = 0; i < 7; i++) {
 		dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
 		dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
 		dev_dbg(dev, "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
 	}
 	dev_dbg(dev, "3 set of Temperatures: =====>\n");
-	for (i=0; i<3; i++) {
+	for (i = 0; i < 3; i++)
 		dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]);
-	}
 
-	for (i=0; i<2; i++) {
-		for (j=0; j<6; j++) {
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < 6; j++) {
 			dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j,
 							data->temp_add[i][j]);
 		}
 	}
 
-	for (i=0; i<7; i++) {
+	for (i = 0; i < 7; i++)
 		dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
-	}
-	dev_dbg(dev, "==========End of the debug message...==================\n");
+
+	dev_dbg(dev, "==========End of the debug message...================\n");
 	dev_dbg(dev, "\n");
 }
 #endif
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 45ec7e7..5929d44 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -1,8 +1,7 @@
-/*
-    w83793.c - Linux kernel driver for hardware monitoring
+/* w83793.c - Linux kernel driver for hardware monitoring
     Copyright (C) 2006 Winbond Electronics Corp.
-                  Yuan Mu
-                  Rudolf Marek <r.marek@assembler.cz>
+		  Yuan Mu
+		  Rudolf Marek <r.marek@assembler.cz>
     Copyright (C) 2009-2010 Sven Anders <anders@anduras.de>, ANDURAS AG.
 		  Watchdog driver part
 		  (Based partially on fschmd driver,
@@ -181,7 +180,7 @@ static inline unsigned long FAN_FROM_REG(u16 val)
 {
 	if ((val >= 0xfff) || (val == 0))
 		return	0;
-	return (1350000UL / val);
+	return 1350000UL / val;
 }
 
 static inline u16 FAN_TO_REG(long rpm)
@@ -193,7 +192,7 @@ static inline u16 FAN_TO_REG(long rpm)
 
 static inline unsigned long TIME_FROM_REG(u8 reg)
 {
-	return (reg * 100);
+	return reg * 100;
 }
 
 static inline u8 TIME_TO_REG(unsigned long val)
@@ -203,7 +202,7 @@ static inline u8 TIME_TO_REG(unsigned long val)
 
 static inline long TEMP_FROM_REG(s8 reg)
 {
-	return (reg * 1000);
+	return reg * 1000;
 }
 
 static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
@@ -337,7 +336,14 @@ store_vrm(struct device *dev, struct device_attribute *attr,
 	  const char *buf, size_t count)
 {
 	struct w83793_data *data = dev_get_drvdata(dev);
-	data->vrm = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	data->vrm = SENSORS_LIMIT(val, 0, 255);
 	return count;
 }
 
@@ -354,7 +360,7 @@ show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
 	int bit = sensor_attr->index & 0x07;
 	u8 val;
 
-	if (ALARM_STATUS == nr) {
+	if (nr == ALARM_STATUS) {
 		val = (data->alarms[index] >> (bit)) & 1;
 	} else {		/* BEEP_ENABLE */
 		val = (data->beeps[index] >> (bit)) & 1;
@@ -374,10 +380,14 @@ store_beep(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index >> 3;
 	int shift = sensor_attr->index & 0x07;
 	u8 beep_bit = 1 << shift;
-	u8 val;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
-	if (val != 0 && val != 1)
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (val > 1)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -403,9 +413,14 @@ store_beep_enable(struct device *dev, struct device_attribute *attr,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	u8 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	if (val != 0 && val != 1)
+	if (val > 1)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -449,8 +464,12 @@ store_chassis_clear(struct device *dev,
 	struct w83793_data *data = i2c_get_clientdata(client);
 	unsigned long val;
 	u8 reg;
+	int err;
 
-	if (kstrtoul(buf, 10, &val) || val != 0)
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	if (val)
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -473,11 +492,10 @@ show_fan(struct device *dev, struct device_attribute *attr, char *buf)
 	struct w83793_data *data = w83793_update_device(dev);
 	u16 val;
 
-	if (FAN_INPUT == nr) {
+	if (nr == FAN_INPUT)
 		val = data->fan[index] & 0x0fff;
-	} else {
+	else
 		val = data->fan_min[index] & 0x0fff;
-	}
 
 	return sprintf(buf, "%lu\n", FAN_FROM_REG(val));
 }
@@ -491,7 +509,13 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	u16 val = FAN_TO_REG(simple_strtoul(buf, NULL, 10));
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	val = FAN_TO_REG(val);
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[index] = val;
@@ -513,7 +537,7 @@ show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
 
-	if (PWM_STOP_TIME == nr)
+	if (nr == PWM_STOP_TIME)
 		val = TIME_FROM_REG(data->pwm_stop_time[index]);
 	else
 		val = (data->pwm[index][nr] & 0x3f) << 2;
@@ -531,17 +555,21 @@ store_pwm(struct device *dev, struct device_attribute *attr,
 	    to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
-	u8 val;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	if (PWM_STOP_TIME == nr) {
-		val = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+	if (nr == PWM_STOP_TIME) {
+		val = TIME_TO_REG(val);
 		data->pwm_stop_time[index] = val;
 		w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index),
 				   val);
 	} else {
-		val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff)
-		      >> 2;
+		val = SENSORS_LIMIT(val, 0, 0xff) >> 2;
 		data->pwm[index][nr] =
 		    w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0;
 		data->pwm[index][nr] |= val;
@@ -563,7 +591,7 @@ show_temp(struct device *dev, struct device_attribute *attr, char *buf)
 	struct w83793_data *data = w83793_update_device(dev);
 	long temp = TEMP_FROM_REG(data->temp[index][nr]);
 
-	if (TEMP_READ == nr && index < 4) {	/* Only TD1-TD4 have low bits */
+	if (nr == TEMP_READ && index < 4) {	/* Only TD1-TD4 have low bits */
 		int low = ((data->temp_low_bits >> (index * 2)) & 0x03) * 250;
 		temp += temp > 0 ? low : -low;
 	}
@@ -580,7 +608,12 @@ store_temp(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	long tmp = simple_strtol(buf, NULL, 10);
+	long tmp;
+	int err;
+
+	err = kstrtol(buf, 10, &tmp);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	data->temp[index][nr] = TEMP_TO_REG(tmp, -128, 127);
@@ -622,11 +655,10 @@ show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
 	tmp = (data->temp_mode[index] >> shift) & mask;
 
 	/* for the internal sensor, found out if diode or thermistor */
-	if (tmp == 1) {
+	if (tmp == 1)
 		tmp = index == 0 ? 3 : 4;
-	} else {
+	else
 		tmp = TO_TEMP_MODE[tmp];
-	}
 
 	return sprintf(buf, "%d\n", tmp);
 }
@@ -642,7 +674,12 @@ store_temp_mode(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	u8 mask = (index < 4) ? 0x03 : 0x01;
 	u8 shift = (index < 4) ? (2 * index) : (index - 4);
-	u8 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	/* transform the sysfs interface values into table above */
 	if ((val == 6) && (index < 4)) {
@@ -681,15 +718,14 @@ show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
 	struct w83793_data *data = w83793_update_device(dev);
 	u32 val = 0;
 
-	if (SETUP_PWM_DEFAULT == nr) {
+	if (nr == SETUP_PWM_DEFAULT)
 		val = (data->pwm_default & 0x3f) << 2;
-	} else if (SETUP_PWM_UPTIME == nr) {
+	else if (nr == SETUP_PWM_UPTIME)
 		val = TIME_FROM_REG(data->pwm_uptime);
-	} else if (SETUP_PWM_DOWNTIME == nr) {
+	else if (nr == SETUP_PWM_DOWNTIME)
 		val = TIME_FROM_REG(data->pwm_downtime);
-	} else if (SETUP_TEMP_CRITICAL == nr) {
+	else if (nr == SETUP_TEMP_CRITICAL)
 		val = TEMP_FROM_REG(data->temp_critical & 0x7f);
-	}
 
 	return sprintf(buf, "%d\n", val);
 }
@@ -703,31 +739,34 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
 	int nr = sensor_attr->nr;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	if (SETUP_PWM_DEFAULT == nr) {
+	if (nr == SETUP_PWM_DEFAULT) {
 		data->pwm_default =
 		    w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0;
-		data->pwm_default |= SENSORS_LIMIT(simple_strtoul(buf, NULL,
-								  10),
-						   0, 0xff) >> 2;
+		data->pwm_default |= SENSORS_LIMIT(val, 0, 0xff) >> 2;
 		w83793_write_value(client, W83793_REG_PWM_DEFAULT,
 							data->pwm_default);
-	} else if (SETUP_PWM_UPTIME == nr) {
-		data->pwm_uptime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+	} else if (nr == SETUP_PWM_UPTIME) {
+		data->pwm_uptime = TIME_TO_REG(val);
 		data->pwm_uptime += data->pwm_uptime == 0 ? 1 : 0;
 		w83793_write_value(client, W83793_REG_PWM_UPTIME,
 							data->pwm_uptime);
-	} else if (SETUP_PWM_DOWNTIME == nr) {
-		data->pwm_downtime = TIME_TO_REG(simple_strtoul(buf, NULL, 10));
+	} else if (nr == SETUP_PWM_DOWNTIME) {
+		data->pwm_downtime = TIME_TO_REG(val);
 		data->pwm_downtime += data->pwm_downtime == 0 ? 1 : 0;
 		w83793_write_value(client, W83793_REG_PWM_DOWNTIME,
 							data->pwm_downtime);
 	} else {		/* SETUP_TEMP_CRITICAL */
 		data->temp_critical =
 		    w83793_read_value(client, W83793_REG_TEMP_CRITICAL) & 0x80;
-		data->temp_critical |= TEMP_TO_REG(simple_strtol(buf, NULL, 10),
-						   0, 0x7f);
+		data->temp_critical |= TEMP_TO_REG(val, 0, 0x7f);
 		w83793_write_value(client, W83793_REG_TEMP_CRITICAL,
 							data->temp_critical);
 	}
@@ -777,12 +816,12 @@ show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf)
 	struct w83793_data *data = w83793_update_device(dev);
 	u32 val;
 
-	if (TEMP_FAN_MAP == nr) {
+	if (nr == TEMP_FAN_MAP) {
 		val = data->temp_fan_map[index];
-	} else if (TEMP_PWM_ENABLE == nr) {
+	} else if (nr == TEMP_PWM_ENABLE) {
 		/* +2 to transfrom into 2 and 3 to conform with sysfs intf */
 		val = ((data->pwm_enable >> index) & 0x01) + 2;
-	} else if (TEMP_CRUISE == nr) {
+	} else if (nr == TEMP_CRUISE) {
 		val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f);
 	} else {		/* TEMP_TOLERANCE */
 		val = data->tolerance[index >> 1] >> ((index & 0x01) ? 4 : 0);
@@ -801,16 +840,20 @@ store_sf_ctrl(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	u32 val;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
-	if (TEMP_FAN_MAP == nr) {
-		val = simple_strtoul(buf, NULL, 10) & 0xff;
+	if (nr == TEMP_FAN_MAP) {
+		val = SENSORS_LIMIT(val, 0, 255);
 		w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val);
 		data->temp_fan_map[index] = val;
-	} else if (TEMP_PWM_ENABLE == nr) {
-		val = simple_strtoul(buf, NULL, 10);
-		if (2 == val || 3 == val) {
+	} else if (nr == TEMP_PWM_ENABLE) {
+		if (val == 2 || val == 3) {
 			data->pwm_enable =
 			    w83793_read_value(client, W83793_REG_PWM_ENABLE);
 			if (val - 2)
@@ -823,12 +866,11 @@ store_sf_ctrl(struct device *dev, struct device_attribute *attr,
 			mutex_unlock(&data->update_lock);
 			return -EINVAL;
 		}
-	} else if (TEMP_CRUISE == nr) {
+	} else if (nr == TEMP_CRUISE) {
 		data->temp_cruise[index] =
 		    w83793_read_value(client, W83793_REG_TEMP_CRUISE(index));
-		val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
 		data->temp_cruise[index] &= 0x80;
-		data->temp_cruise[index] |= val;
+		data->temp_cruise[index] |= TEMP_TO_REG(val, 0, 0x7f);
 
 		w83793_write_value(client, W83793_REG_TEMP_CRUISE(index),
 						data->temp_cruise[index]);
@@ -838,9 +880,8 @@ store_sf_ctrl(struct device *dev, struct device_attribute *attr,
 		data->tolerance[i] =
 		    w83793_read_value(client, W83793_REG_TEMP_TOL(i));
 
-		val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x0f);
 		data->tolerance[i] &= ~(0x0f << shift);
-		data->tolerance[i] |= val << shift;
+		data->tolerance[i] |= TEMP_TO_REG(val, 0, 0x0f) << shift;
 		w83793_write_value(client, W83793_REG_TEMP_TOL(i),
 							data->tolerance[i]);
 	}
@@ -871,7 +912,13 @@ store_sf2_pwm(struct device *dev, struct device_attribute *attr,
 	    to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
-	u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 0xff) >> 2;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	val = SENSORS_LIMIT(val, 0, 0xff) >> 2;
 
 	mutex_lock(&data->update_lock);
 	data->sf2_pwm[index][nr] =
@@ -906,7 +953,13 @@ store_sf2_temp(struct device *dev, struct device_attribute *attr,
 	    to_sensor_dev_attr_2(attr);
 	int nr = sensor_attr->nr;
 	int index = sensor_attr->index;
-	u8 val = TEMP_TO_REG(simple_strtol(buf, NULL, 10), 0, 0x7f);
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
+	val = TEMP_TO_REG(val, 0, 0x7f);
 
 	mutex_lock(&data->update_lock);
 	data->sf2_temp[index][nr] =
@@ -948,17 +1001,19 @@ store_in(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83793_data *data = i2c_get_clientdata(client);
-	u32 val;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	val = (val + scale_in[index] / 2) / scale_in[index];
 
-	val =
-	    (simple_strtoul(buf, NULL, 10) +
-	     scale_in[index] / 2) / scale_in[index];
 	mutex_lock(&data->update_lock);
 	if (index > 2) {
 		/* fix the limit values of 5VDD and 5VSB to ALARM mechanism */
-		if (1 == nr || 2 == nr) {
+		if (nr == 1 || nr == 2)
 			val -= scale_in_add[index] / scale_in[index];
-		}
 		val = SENSORS_LIMIT(val, 0, 255);
 	} else {
 		val = SENSORS_LIMIT(val, 0, 0x3FF);
@@ -1143,9 +1198,8 @@ static struct sensor_device_attribute_2 sda_single_files[] = {
 
 static void w83793_init_client(struct i2c_client *client)
 {
-	if (reset) {
+	if (reset)
 		w83793_write_value(client, W83793_REG_CONFIG, 0x80);
-	}
 
 	/* Start monitoring */
 	w83793_write_value(client, W83793_REG_CONFIG,
@@ -1556,9 +1610,8 @@ w83793_detect_subclients(struct i2c_client *client)
 	}
 
 	tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
-	if (!(tmp & 0x08)) {
+	if (!(tmp & 0x08))
 		data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7));
-	}
 	if (!(tmp & 0x80)) {
 		if ((data->lm75[0] != NULL)
 		    && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
@@ -1591,9 +1644,8 @@ static int w83793_detect(struct i2c_client *client,
 	struct i2c_adapter *adapter = client->adapter;
 	unsigned short address = client->addr;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
-	}
 
 	bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
 
@@ -1723,7 +1775,7 @@ static int w83793_probe(struct i2c_client *client,
 	}
 
 	/* check the temp1-6 mode, ignore former AMDSI selected inputs */
-	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]);
+	tmp = w83793_read_value(client, W83793_REG_TEMP_MODE[0]);
 	if (tmp & 0x01)
 		data->has_temp |= 0x01;
 	if (tmp & 0x04)
@@ -1733,7 +1785,7 @@ static int w83793_probe(struct i2c_client *client,
 	if (tmp & 0x40)
 		data->has_temp |= 0x08;
 
-	tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]);
+	tmp = w83793_read_value(client, W83793_REG_TEMP_MODE[1]);
 	if (tmp & 0x01)
 		data->has_temp |= 0x10;
 	if (tmp & 0x02)
@@ -1940,9 +1992,8 @@ static void w83793_update_nonvolatile(struct device *dev)
 
 	for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {
 		/* Update the Fan measured value and limits */
-		if (!(data->has_fan & (1 << i))) {
+		if (!(data->has_fan & (1 << i)))
 			continue;
-		}
 		data->fan_min[i] =
 		    w83793_read_value(client, W83793_REG_FAN_MIN(i)) << 8;
 		data->fan_min[i] |=
@@ -1997,9 +2048,8 @@ static void w83793_update_nonvolatile(struct device *dev)
 	    w83793_read_value(client, W83793_REG_TEMP_CRITICAL);
 	data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP);
 
-	for (i = 0; i < ARRAY_SIZE(data->beeps); i++) {
+	for (i = 0; i < ARRAY_SIZE(data->beeps); i++)
 		data->beeps[i] = w83793_read_value(client, W83793_REG_BEEP(i));
-	}
 
 	data->last_nonvolatile = jiffies;
 }
@@ -2025,9 +2075,8 @@ static struct w83793_data *w83793_update_device(struct device *dev)
 	    w83793_read_value(client, W83793_REG_IN_LOW_BITS[IN_READ]);
 
 	for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
-		if (!(data->has_fan & (1 << i))) {
+		if (!(data->has_fan & (1 << i)))
 			continue;
-		}
 		data->fan[i] =
 		    w83793_read_value(client, W83793_REG_FAN(i)) << 8;
 		data->fan[i] |=
@@ -2103,16 +2152,16 @@ static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value)
 
 	new_bank |= data->bank & 0xfc;
 	if (data->bank != new_bank) {
-		if ((res = i2c_smbus_write_byte_data
-		    (client, W83793_REG_BANKSEL, new_bank)) >= 0)
-			data->bank = new_bank;
-		else {
+		res = i2c_smbus_write_byte_data(client, W83793_REG_BANKSEL,
+						new_bank);
+		if (res < 0) {
 			dev_err(&client->dev,
 				"set bank to %d failed, fall back "
 				"to bank %d, write reg 0x%x error\n",
 				new_bank, data->bank, reg);
 			goto END;
 		}
+		data->bank = new_bank;
 	}
 
 	res = i2c_smbus_write_byte_data(client, reg & 0xff, value);
diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c
index 20781de..edfc1ec 100644
--- a/drivers/hwmon/w83l785ts.c
+++ b/drivers/hwmon/w83l785ts.c
@@ -86,7 +86,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev);
 /*
  * Driver data (common to all clients)
  */
- 
+
 static const struct i2c_device_id w83l785ts_id[] = {
 	{ "w83l785ts", 0 },
 	{ }
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 063bd95..6eac5d9 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
 
 #define W83L786NG_REG_CONFIG		0x40
 #define W83L786NG_REG_ALARM1		0x41
-#define W83L786NG_REG_ALARM2 		0x42
+#define W83L786NG_REG_ALARM2		0x42
 #define W83L786NG_REG_GPIO_EN		0x47
 #define W83L786NG_REG_MAN_ID2		0x4C
 #define W83L786NG_REG_MAN_ID1		0x4D
@@ -89,19 +89,21 @@ FAN_TO_REG(long rpm, int div)
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
-#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+#define FAN_FROM_REG(val, div)	((val) == 0   ? -1 : \
 				((val) == 255 ? 0 : \
 				1350000 / ((val) * (div))))
 
 /* for temp */
-#define TEMP_TO_REG(val)	(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
-				    : (val)) / 1000, 0, 0xff))
-#define TEMP_FROM_REG(val)	(((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+#define TEMP_TO_REG(val)	(SENSORS_LIMIT(((val) < 0 ? \
+						(val) + 0x100 * 1000 \
+						: (val)) / 1000, 0, 0xff))
+#define TEMP_FROM_REG(val)	(((val) & 0x80 ? \
+				  (val) - 0x100 : (val)) * 1000)
 
 /* The analog voltage inputs have 8mV LSB. Since the sysfs output is
    in mV as would be measured on the chip input pin, need to just
    multiply/divide by 8 to translate from/to register values. */
-#define IN_TO_REG(val)          (SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
+#define IN_TO_REG(val)		(SENSORS_LIMIT((((val) + 4) / 8), 0, 255))
 #define IN_FROM_REG(val)	((val) * 8)
 
 #define DIV_FROM_REG(val)	(1 << (val))
@@ -116,7 +118,7 @@ DIV_TO_REG(long val)
 			break;
 		val >>= 1;
 	}
-	return ((u8) i);
+	return (u8)i;
 }
 
 struct w83l786ng_data {
@@ -186,11 +188,11 @@ w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value)
 #define show_in_reg(reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
-           char *buf) \
+	   char *buf) \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
-	return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \
 }
 
 show_in_reg(in)
@@ -199,13 +201,16 @@ show_in_reg(in_max)
 
 #define store_in_reg(REG, reg) \
 static ssize_t \
-store_in_##reg (struct device *dev, struct device_attribute *attr, \
-		const char *buf, size_t count) \
+store_in_##reg(struct device *dev, struct device_attribute *attr, \
+	       const char *buf, size_t count) \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct w83l786ng_data *data = i2c_get_clientdata(client); \
-	unsigned long val = simple_strtoul(buf, NULL, 10); \
+	unsigned long val; \
+	int err = kstrtoul(buf, 10, &val); \
+	if (err) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = IN_TO_REG(val); \
 	w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \
@@ -241,8 +246,8 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 { \
 	int nr = to_sensor_dev_attr(attr)->index; \
 	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
-        return sprintf(buf,"%d\n", \
-                FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+	return sprintf(buf, "%d\n", \
+		FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \
 }
 
 show_fan_reg(fan);
@@ -255,9 +260,13 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	u32 val;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtoul(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
 	w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr),
@@ -294,11 +303,18 @@ store_fan_div(struct device *dev, struct device_attribute *attr,
 	u8 keep_mask = 0;
 	u8 new_shift = 0;
 
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
 	/* Save fan_min */
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
 
-	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+	data->fan_div[nr] = DIV_TO_REG(val);
 
 	switch (nr) {
 	case 0:
@@ -371,16 +387,20 @@ store_temp(struct device *dev, struct device_attribute *attr,
 	int index = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	s32 val;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err)
+		return err;
 
-	val = simple_strtol(buf, NULL, 10);
 	mutex_lock(&data->update_lock);
 	data->temp[nr][index] = TEMP_TO_REG(val);
 	w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index],
 			      data->temp[nr][index]);
 	mutex_unlock(&data->update_lock);
 
-        return count;
+	return count;
 }
 
 static struct sensor_device_attribute_2 sda_temp_input[] = {
@@ -403,8 +423,8 @@ static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
 };
 
 #define show_pwm_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
-			   char *buf) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			  char *buf) \
 { \
 	struct w83l786ng_data *data = w83l786ng_update_device(dev); \
 	int nr = to_sensor_dev_attr(attr)->index; \
@@ -422,8 +442,13 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
 	u8 reg;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	if (val > 1)
 		return -EINVAL;
@@ -445,7 +470,13 @@ store_pwm(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	val = SENSORS_LIMIT(val, 0, 255);
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = val;
@@ -461,11 +492,15 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	u32 val = simple_strtoul(buf, NULL, 10);
-
 	u8 reg;
+	unsigned long val;
+	int err;
 
-	if (!val || (val > 2))  /* only modes 1 and 2 are supported */
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+
+	if (!val || val > 2)  /* only modes 1 and 2 are supported */
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
@@ -513,10 +548,13 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 	int nr = to_sensor_dev_attr(attr)->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83l786ng_data *data = i2c_get_clientdata(client);
-	u32 val;
 	u8 tol_tmp, tol_mask;
+	unsigned long val;
+	int err;
 
-	val = simple_strtoul(buf, NULL, 10);
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
 
 	mutex_lock(&data->update_lock);
 	tol_mask = w83l786ng_read_value(client,
@@ -524,9 +562,8 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 	tol_tmp = SENSORS_LIMIT(val, 0, 15);
 	tol_tmp &= 0x0f;
 	data->tolerance[nr] = tol_tmp;
-	if (nr == 1) {
+	if (nr == 1)
 		tol_tmp <<= 4;
-	}
 
 	w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE,
 			      tol_mask | tol_tmp);
@@ -591,9 +628,8 @@ w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info)
 	u16 man_id;
 	u8 chip_id;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
-	}
 
 	/* Detection */
 	if ((w83l786ng_read_value(client, W83L786NG_REG_CONFIG) & 0x80)) {
@@ -652,7 +688,8 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	data->fan_div[1] = (reg_tmp >> 4) & 0x07;
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group)))
+	err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group);
+	if (err)
 		goto exit_remove;
 
 	data->hwmon_dev = hwmon_device_register(dev);
diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c
index 9b598ed..23b44de 100644
--- a/drivers/hwmon/wm831x-hwmon.c
+++ b/drivers/hwmon/wm831x-hwmon.c
@@ -40,7 +40,7 @@ static ssize_t show_name(struct device *dev,
 	return sprintf(buf, "wm831x\n");
 }
 
-static const char *input_names[] = {
+static const char * const input_names[] = {
 	[WM831X_AUX_SYSVDD]    = "SYSVDD",
 	[WM831X_AUX_USB]       = "USB",
 	[WM831X_AUX_BKUP_BATT] = "Backup battery",
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 5bc2839..729428e 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -253,7 +253,7 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
 		if (page_is_high)
 			local_irq_save(flags);
 
-		buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset;
+		buf = kmap_atomic(page) + offset;
 
 		cmd->nleft -= nr_bytes;
 		cmd->cursg_ofs += nr_bytes;
@@ -269,7 +269,7 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
 		else
 			hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes);
 
-		kunmap_atomic(buf, KM_BIO_SRC_IRQ);
+		kunmap_atomic(buf);
 
 		if (page_is_high)
 			local_irq_restore(flags);
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
index fb88d68..2033a92 100644
--- a/drivers/infiniband/ulp/iser/iser_memory.c
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -73,11 +73,11 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
 
 		p = mem;
 		for_each_sg(sgl, sg, data->size, i) {
-			from = kmap_atomic(sg_page(sg), KM_USER0);
+			from = kmap_atomic(sg_page(sg));
 			memcpy(p,
 			       from + sg->offset,
 			       sg->length);
-			kunmap_atomic(from, KM_USER0);
+			kunmap_atomic(from);
 			p += sg->length;
 		}
 	}
@@ -133,11 +133,11 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_task *iser_task,
 
 		p = mem;
 		for_each_sg(sgl, sg, sg_size, i) {
-			to = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+			to = kmap_atomic(sg_page(sg));
 			memcpy(to + sg->offset,
 			       p,
 			       sg->length);
-			kunmap_atomic(to, KM_SOFTIRQ0);
+			kunmap_atomic(to);
 			p += sg->length;
 		}
 	}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index c957c34..48f914a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -403,6 +403,13 @@ config LEDS_MAX8997
 	  This option enables support for on-chip LED drivers on
 	  MAXIM MAX8997 PMIC.
 
+config LEDS_OT200
+	tristate "LED support for the Bachmann OT200"
+	depends on LEDS_CLASS
+	help
+	  This option enables support for the LEDs on the Bachmann OT200.
+	  Say Y to enable LEDs on the Bachmann OT200.
+
 config LEDS_TRIGGERS
 	bool "LED Trigger support"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index b8a9723..1fc6875 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_LEDS_LP5523)		+= leds-lp5523.o
 obj-$(CONFIG_LEDS_TCA6507)		+= leds-tca6507.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)		+= leds-hp6xx.o
+obj-$(CONFIG_LEDS_OT200)		+= leds-ot200.o
 obj-$(CONFIG_LEDS_FSG)			+= leds-fsg.o
 obj-$(CONFIG_LEDS_PCA955X)		+= leds-pca955x.o
 obj-$(CONFIG_LEDS_DA903X)		+= leds-da903x.o
diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c
new file mode 100644
index 0000000..c464682
--- /dev/null
+++ b/drivers/leds/leds-ot200.c
@@ -0,0 +1,171 @@
+/*
+ * Bachmann ot200 leds driver.
+ *
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *         Christian Gmeiner <christian.gmeiner@gmail.com>
+ *
+ * License: GPL as published by the FSF.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+
+struct ot200_led {
+	struct led_classdev cdev;
+	const char *name;
+	unsigned long port;
+	u8 mask;
+};
+
+/*
+ * The device has three leds on the back panel (led_err, led_init and led_run)
+ * and can handle up to seven leds on the front panel.
+ */
+
+static struct ot200_led leds[] = {
+	{
+		.name = "led_run",
+		.port = 0x5a,
+		.mask = BIT(0),
+	},
+	{
+		.name = "led_init",
+		.port = 0x5a,
+		.mask = BIT(1),
+	},
+	{
+		.name = "led_err",
+		.port = 0x5a,
+		.mask = BIT(2),
+	},
+	{
+		.name = "led_1",
+		.port = 0x49,
+		.mask = BIT(7),
+	},
+	{
+		.name = "led_2",
+		.port = 0x49,
+		.mask = BIT(6),
+	},
+	{
+		.name = "led_3",
+		.port = 0x49,
+		.mask = BIT(5),
+	},
+	{
+		.name = "led_4",
+		.port = 0x49,
+		.mask = BIT(4),
+	},
+	{
+		.name = "led_5",
+		.port = 0x49,
+		.mask = BIT(3),
+	},
+	{
+		.name = "led_6",
+		.port = 0x49,
+		.mask = BIT(2),
+	},
+	{
+		.name = "led_7",
+		.port = 0x49,
+		.mask = BIT(1),
+	}
+};
+
+static DEFINE_SPINLOCK(value_lock);
+
+/*
+ * we need to store the current led states, as it is not
+ * possible to read the current led state via inb().
+ */
+static u8 leds_back;
+static u8 leds_front;
+
+static void ot200_led_brightness_set(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	struct ot200_led *led = container_of(led_cdev, struct ot200_led, cdev);
+	u8 *val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&value_lock, flags);
+
+	if (led->port == 0x49)
+		val = &leds_front;
+	else if (led->port == 0x5a)
+		val = &leds_back;
+	else
+		BUG();
+
+	if (value == LED_OFF)
+		*val &= ~led->mask;
+	else
+		*val |= led->mask;
+
+	outb(*val, led->port);
+	spin_unlock_irqrestore(&value_lock, flags);
+}
+
+static int __devinit ot200_led_probe(struct platform_device *pdev)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(leds); i++) {
+
+		leds[i].cdev.name = leds[i].name;
+		leds[i].cdev.brightness_set = ot200_led_brightness_set;
+
+		ret = led_classdev_register(&pdev->dev, &leds[i].cdev);
+		if (ret < 0)
+			goto err;
+	}
+
+	leds_front = 0;		/* turn off all front leds */
+	leds_back = BIT(1);	/* turn on init led */
+	outb(leds_front, 0x49);
+	outb(leds_back, 0x5a);
+
+	return 0;
+
+err:
+	for (i = i - 1; i >= 0; i--)
+		led_classdev_unregister(&leds[i].cdev);
+
+	return ret;
+}
+
+static int __devexit ot200_led_remove(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(leds); i++)
+		led_classdev_unregister(&leds[i].cdev);
+
+	return 0;
+}
+
+static struct platform_driver ot200_led_driver = {
+	.probe		= ot200_led_probe,
+	.remove		= __devexit_p(ot200_led_remove),
+	.driver		= {
+		.name	= "leds-ot200",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(ot200_led_driver);
+
+MODULE_AUTHOR("Sebastian A. Siewior <bigeasy@linutronix.de>");
+MODULE_DESCRIPTION("ot200 LED driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:leds-ot200");
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index cdf36b1..045e086 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -457,7 +457,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
 		return;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page);
 	sb->events = cpu_to_le64(bitmap->mddev->events);
 	if (bitmap->mddev->events < bitmap->events_cleared)
 		/* rocking back to read-only */
@@ -467,7 +467,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
 	/* Just in case these have been changed via sysfs: */
 	sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);
 	sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);
-	kunmap_atomic(sb, KM_USER0);
+	kunmap_atomic(sb);
 	write_page(bitmap, bitmap->sb_page, 1);
 }
 
@@ -478,7 +478,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
 
 	if (!bitmap || !bitmap->sb_page)
 		return;
-	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page);
 	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
 	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
 	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
@@ -497,7 +497,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
 	printk(KERN_DEBUG "     sync size: %llu KB\n",
 			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
 	printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
-	kunmap_atomic(sb, KM_USER0);
+	kunmap_atomic(sb);
 }
 
 /*
@@ -525,7 +525,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
 	}
 	bitmap->sb_page->index = 0;
 
-	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page);
 
 	sb->magic = cpu_to_le32(BITMAP_MAGIC);
 	sb->version = cpu_to_le32(BITMAP_MAJOR_HI);
@@ -533,7 +533,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
 	chunksize = bitmap->mddev->bitmap_info.chunksize;
 	BUG_ON(!chunksize);
 	if (!is_power_of_2(chunksize)) {
-		kunmap_atomic(sb, KM_USER0);
+		kunmap_atomic(sb);
 		printk(KERN_ERR "bitmap chunksize not a power of 2\n");
 		return -EINVAL;
 	}
@@ -571,7 +571,7 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
 	bitmap->flags |= BITMAP_HOSTENDIAN;
 	sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN);
 
-	kunmap_atomic(sb, KM_USER0);
+	kunmap_atomic(sb);
 
 	return 0;
 }
@@ -603,7 +603,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
 		return err;
 	}
 
-	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page);
 
 	chunksize = le32_to_cpu(sb->chunksize);
 	daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
@@ -664,7 +664,7 @@ success:
 		bitmap->events_cleared = bitmap->mddev->events;
 	err = 0;
 out:
-	kunmap_atomic(sb, KM_USER0);
+	kunmap_atomic(sb);
 	if (err)
 		bitmap_print_sb(bitmap);
 	return err;
@@ -689,7 +689,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
 		return 0;
 	}
 	spin_unlock_irqrestore(&bitmap->lock, flags);
-	sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+	sb = kmap_atomic(bitmap->sb_page);
 	old = le32_to_cpu(sb->state) & bits;
 	switch (op) {
 	case MASK_SET:
@@ -703,7 +703,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
 	default:
 		BUG();
 	}
-	kunmap_atomic(sb, KM_USER0);
+	kunmap_atomic(sb);
 	return old;
 }
 
@@ -881,12 +881,12 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
 	bit = file_page_offset(bitmap, chunk);
 
 	/* set the bit */
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (bitmap->flags & BITMAP_HOSTENDIAN)
 		set_bit(bit, kaddr);
 	else
 		__set_bit_le(bit, kaddr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	pr_debug("set file bit %lu page %lu\n", bit, page->index);
 	/* record page number so it gets flushed to disk when unplug occurs */
 	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
@@ -1050,10 +1050,10 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 				 * if bitmap is out of date, dirty the
 				 * whole page and write it out
 				 */
-				paddr = kmap_atomic(page, KM_USER0);
+				paddr = kmap_atomic(page);
 				memset(paddr + offset, 0xff,
 				       PAGE_SIZE - offset);
-				kunmap_atomic(paddr, KM_USER0);
+				kunmap_atomic(paddr);
 				write_page(bitmap, page, 1);
 
 				ret = -EIO;
@@ -1061,12 +1061,12 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
 					goto err;
 			}
 		}
-		paddr = kmap_atomic(page, KM_USER0);
+		paddr = kmap_atomic(page);
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
 			b = test_bit(bit, paddr);
 		else
 			b = test_bit_le(bit, paddr);
-		kunmap_atomic(paddr, KM_USER0);
+		kunmap_atomic(paddr);
 		if (b) {
 			/* if the disk bit is set, set the memory bit */
 			int needed = ((sector_t)(i+1) << (CHUNK_BLOCK_SHIFT(bitmap))
@@ -1209,10 +1209,10 @@ void bitmap_daemon_work(struct mddev *mddev)
 			    mddev->bitmap_info.external == 0) {
 				bitmap_super_t *sb;
 				bitmap->need_sync = 0;
-				sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+				sb = kmap_atomic(bitmap->sb_page);
 				sb->events_cleared =
 					cpu_to_le64(bitmap->events_cleared);
-				kunmap_atomic(sb, KM_USER0);
+				kunmap_atomic(sb);
 				write_page(bitmap, bitmap->sb_page, 1);
 			}
 			spin_lock_irqsave(&bitmap->lock, flags);
@@ -1235,7 +1235,7 @@ void bitmap_daemon_work(struct mddev *mddev)
 						  -1);
 
 				/* clear the bit */
-				paddr = kmap_atomic(page, KM_USER0);
+				paddr = kmap_atomic(page);
 				if (bitmap->flags & BITMAP_HOSTENDIAN)
 					clear_bit(file_page_offset(bitmap, j),
 						  paddr);
@@ -1244,7 +1244,7 @@ void bitmap_daemon_work(struct mddev *mddev)
 						file_page_offset(bitmap,
 								 j),
 						paddr);
-				kunmap_atomic(paddr, KM_USER0);
+				kunmap_atomic(paddr);
 			} else if (*bmc <= 2) {
 				*bmc = 1; /* maybe clear the bit next time */
 				set_page_attr(bitmap, page, BITMAP_PAGE_PENDING);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 8c2a000..db6b516 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -590,9 +590,9 @@ static int crypt_iv_lmk_gen(struct crypt_config *cc, u8 *iv,
 	int r = 0;
 
 	if (bio_data_dir(dmreq->ctx->bio_in) == WRITE) {
-		src = kmap_atomic(sg_page(&dmreq->sg_in), KM_USER0);
+		src = kmap_atomic(sg_page(&dmreq->sg_in));
 		r = crypt_iv_lmk_one(cc, iv, dmreq, src + dmreq->sg_in.offset);
-		kunmap_atomic(src, KM_USER0);
+		kunmap_atomic(src);
 	} else
 		memset(iv, 0, cc->iv_size);
 
@@ -608,14 +608,14 @@ static int crypt_iv_lmk_post(struct crypt_config *cc, u8 *iv,
 	if (bio_data_dir(dmreq->ctx->bio_in) == WRITE)
 		return 0;
 
-	dst = kmap_atomic(sg_page(&dmreq->sg_out), KM_USER0);
+	dst = kmap_atomic(sg_page(&dmreq->sg_out));
 	r = crypt_iv_lmk_one(cc, iv, dmreq, dst + dmreq->sg_out.offset);
 
 	/* Tweak the first block of plaintext sector */
 	if (!r)
 		crypto_xor(dst + dmreq->sg_out.offset, iv, cc->iv_size);
 
-	kunmap_atomic(dst, KM_USER0);
+	kunmap_atomic(dst);
 	return r;
 }
 
diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c
index 69cc816..7338cb2 100644
--- a/drivers/media/video/ivtv/ivtv-udma.c
+++ b/drivers/media/video/ivtv/ivtv-udma.c
@@ -57,9 +57,9 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info
 			if (dma->bouncemap[map_offset] == NULL)
 				return -1;
 			local_irq_save(flags);
-			src = kmap_atomic(dma->map[map_offset], KM_BOUNCE_READ) + offset;
+			src = kmap_atomic(dma->map[map_offset]) + offset;
 			memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
-			kunmap_atomic(src, KM_BOUNCE_READ);
+			kunmap_atomic(src);
 			local_irq_restore(flags);
 			sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
 		}
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c
index a74a797..eaabc27 100644
--- a/drivers/media/video/omap3isp/ispccdc.c
+++ b/drivers/media/video/omap3isp/ispccdc.c
@@ -1407,7 +1407,7 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
 static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
 {
 	struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
-	struct video_device *vdev = &ccdc->subdev.devnode;
+	struct video_device *vdev = ccdc->subdev.devnode;
 	struct v4l2_event event;
 
 	memset(&event, 0, sizeof(event));
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 5319e9b..c37d375 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -325,7 +325,7 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
 			p_cnt = min(p_cnt, length);
 
 			local_irq_save(flags);
-			buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
+			buf = kmap_atomic(pg) + p_off;
 		} else {
 			buf = host->req->data + host->block_pos;
 			p_cnt = host->req->data_len - host->block_pos;
@@ -341,7 +341,7 @@ static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
 				 : jmb38x_ms_read_reg_data(host, buf, p_cnt);
 
 		if (host->req->long_data) {
-			kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
+			kunmap_atomic(buf - p_off);
 			local_irq_restore(flags);
 		}
 
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index 6902b83..7bafa72 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -210,7 +210,7 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
 			p_cnt = min(p_cnt, length);
 
 			local_irq_save(flags);
-			buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
+			buf = kmap_atomic(pg) + p_off;
 		} else {
 			buf = host->req->data + host->block_pos;
 			p_cnt = host->req->data_len - host->block_pos;
@@ -221,7 +221,7 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
 			 : tifm_ms_read_data(host, buf, p_cnt);
 
 		if (host->req->long_data) {
-			kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
+			kunmap_atomic(buf - p_off);
 			local_irq_restore(flags);
 		}
 
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 0cad48a..176b78e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1080,6 +1080,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 	struct mmc_blk_request *brq = &mqrq->brq;
 	struct request *req = mqrq->req;
 	struct mmc_blk_data *md = mq->data;
+	bool do_data_tag;
 
 	/*
 	 * Reliable writes are used to implement Forced Unit Access and
@@ -1156,6 +1157,16 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 		mmc_apply_rel_rw(brq, card, req);
 
 	/*
+	 * Data tag is used only during writing meta data to speed
+	 * up write and any subsequent read of this meta data
+	 */
+	do_data_tag = (card->ext_csd.data_tag_unit_size) &&
+		(req->cmd_flags & REQ_META) &&
+		(rq_data_dir(req) == WRITE) &&
+		((brq->data.blocks * brq->data.blksz) >=
+		 card->ext_csd.data_tag_unit_size);
+
+	/*
 	 * Pre-defined multi-block transfers are preferable to
 	 * open ended-ones (and necessary for reliable writes).
 	 * However, it is not sufficient to just send CMD23,
@@ -1173,13 +1184,13 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 	 * We'll avoid using CMD23-bounded multiblock writes for
 	 * these, while retaining features like reliable writes.
 	 */
-
-	if ((md->flags & MMC_BLK_CMD23) &&
-	    mmc_op_multi(brq->cmd.opcode) &&
-	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23))) {
+	if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
+	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
+	     do_data_tag)) {
 		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
 		brq->sbc.arg = brq->data.blocks |
-			(do_rel_wr ? (1 << 31) : 0);
+			(do_rel_wr ? (1 << 31) : 0) |
+			(do_data_tag ? (1 << 29) : 0);
 		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		brq->mrq.sbc = &brq->sbc;
 	}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 59b9ba5..dc03291 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -519,6 +519,20 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 			ext_csd[EXT_CSD_CACHE_SIZE + 1] << 8 |
 			ext_csd[EXT_CSD_CACHE_SIZE + 2] << 16 |
 			ext_csd[EXT_CSD_CACHE_SIZE + 3] << 24;
+
+		if (ext_csd[EXT_CSD_DATA_SECTOR_SIZE] == 1)
+			card->ext_csd.data_sector_size = 4096;
+		else
+			card->ext_csd.data_sector_size = 512;
+
+		if ((ext_csd[EXT_CSD_DATA_TAG_SUPPORT] & 1) &&
+		    (ext_csd[EXT_CSD_TAG_UNIT_SIZE] <= 8)) {
+			card->ext_csd.data_tag_unit_size =
+			((unsigned int) 1 << ext_csd[EXT_CSD_TAG_UNIT_SIZE]) *
+			(card->ext_csd.data_sector_size);
+		} else {
+			card->ext_csd.data_tag_unit_size = 0;
+		}
 	}
 
 out:
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index e1e122f..9bcd1f4 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -2526,12 +2526,10 @@ static void cfi_intelext_restore_locks(struct mtd_info *mtd)
 		if (!region->lockmap)
 			continue;
 
-		for (block = 0; block < region->numblocks; block++) {
+		for_each_clear_bit(block, region->lockmap, region->numblocks) {
 			len = region->erasesize;
 			adr = region->offset + block * len;
-
-			if (!test_bit(block, region->lockmap))
-				cfi_intelext_unlock(mtd, adr, len);
+			cfi_intelext_unlock(mtd, adr, len);
 		}
 	}
 }
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 8d70895..e2d94bb 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -59,6 +59,9 @@ static void cfi_amdstd_resume (struct mtd_info *);
 static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *);
 static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 
+static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+				  size_t *retlen, const u_char *buf);
+
 static void cfi_amdstd_destroy(struct mtd_info *);
 
 struct mtd_info *cfi_cmdset_0002(struct map_info *, int);
@@ -443,6 +446,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
 	pr_debug("MTD %s(): write buffer size %d\n", __func__,
 			mtd->writebufsize);
 
+	mtd->panic_write = cfi_amdstd_panic_write;
 	mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
 
 	if (cfi->cfi_mode==CFI_MODE_CFI){
@@ -1562,6 +1566,242 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
 	return 0;
 }
 
+/*
+ * Wait for the flash chip to become ready to write data
+ *
+ * This is only called during the panic_write() path. When panic_write()
+ * is called, the kernel is in the process of a panic, and will soon be
+ * dead. Therefore we don't take any locks, and attempt to get access
+ * to the chip as soon as possible.
+ */
+static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip,
+				 unsigned long adr)
+{
+	struct cfi_private *cfi = map->fldrv_priv;
+	int retries = 10;
+	int i;
+
+	/*
+	 * If the driver thinks the chip is idle, and no toggle bits
+	 * are changing, then the chip is actually idle for sure.
+	 */
+	if (chip->state == FL_READY && chip_ready(map, adr))
+		return 0;
+
+	/*
+	 * Try several times to reset the chip and then wait for it
+	 * to become idle. The upper limit of a few milliseconds of
+	 * delay isn't a big problem: the kernel is dying anyway. It
+	 * is more important to save the messages.
+	 */
+	while (retries > 0) {
+		const unsigned long timeo = (HZ / 1000) + 1;
+
+		/* send the reset command */
+		map_write(map, CMD(0xF0), chip->start);
+
+		/* wait for the chip to become ready */
+		for (i = 0; i < jiffies_to_usecs(timeo); i++) {
+			if (chip_ready(map, adr))
+				return 0;
+
+			udelay(1);
+		}
+	}
+
+	/* the chip never became ready */
+	return -EBUSY;
+}
+
+/*
+ * Write out one word of data to a single flash chip during a kernel panic
+ *
+ * This is only called during the panic_write() path. When panic_write()
+ * is called, the kernel is in the process of a panic, and will soon be
+ * dead. Therefore we don't take any locks, and attempt to get access
+ * to the chip as soon as possible.
+ *
+ * The implementation of this routine is intentionally similar to
+ * do_write_oneword(), in order to ease code maintenance.
+ */
+static int do_panic_write_oneword(struct map_info *map, struct flchip *chip,
+				  unsigned long adr, map_word datum)
+{
+	const unsigned long uWriteTimeout = (HZ / 1000) + 1;
+	struct cfi_private *cfi = map->fldrv_priv;
+	int retry_cnt = 0;
+	map_word oldd;
+	int ret = 0;
+	int i;
+
+	adr += chip->start;
+
+	ret = cfi_amdstd_panic_wait(map, chip, adr);
+	if (ret)
+		return ret;
+
+	pr_debug("MTD %s(): PANIC WRITE 0x%.8lx(0x%.8lx)\n",
+			__func__, adr, datum.x[0]);
+
+	/*
+	 * Check for a NOP for the case when the datum to write is already
+	 * present - it saves time and works around buggy chips that corrupt
+	 * data at other locations when 0xff is written to a location that
+	 * already contains 0xff.
+	 */
+	oldd = map_read(map, adr);
+	if (map_word_equal(map, oldd, datum)) {
+		pr_debug("MTD %s(): NOP\n", __func__);
+		goto op_done;
+	}
+
+	ENABLE_VPP(map);
+
+retry:
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL);
+	map_write(map, datum, adr);
+
+	for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
+		if (chip_ready(map, adr))
+			break;
+
+		udelay(1);
+	}
+
+	if (!chip_good(map, adr, datum)) {
+		/* reset on all failures. */
+		map_write(map, CMD(0xF0), chip->start);
+		/* FIXME - should have reset delay before continuing */
+
+		if (++retry_cnt <= MAX_WORD_RETRIES)
+			goto retry;
+
+		ret = -EIO;
+	}
+
+op_done:
+	DISABLE_VPP(map);
+	return ret;
+}
+
+/*
+ * Write out some data during a kernel panic
+ *
+ * This is used by the mtdoops driver to save the dying messages from a
+ * kernel which has panic'd.
+ *
+ * This routine ignores all of the locking used throughout the rest of the
+ * driver, in order to ensure that the data gets written out no matter what
+ * state this driver (and the flash chip itself) was in when the kernel crashed.
+ *
+ * The implementation of this routine is intentionally similar to
+ * cfi_amdstd_write_words(), in order to ease code maintenance.
+ */
+static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
+				  size_t *retlen, const u_char *buf)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+	unsigned long ofs, chipstart;
+	int ret = 0;
+	int chipnum;
+
+	*retlen = 0;
+	if (!len)
+		return 0;
+
+	chipnum = to >> cfi->chipshift;
+	ofs = to - (chipnum << cfi->chipshift);
+	chipstart = cfi->chips[chipnum].start;
+
+	/* If it's not bus aligned, do the first byte write */
+	if (ofs & (map_bankwidth(map) - 1)) {
+		unsigned long bus_ofs = ofs & ~(map_bankwidth(map) - 1);
+		int i = ofs - bus_ofs;
+		int n = 0;
+		map_word tmp_buf;
+
+		ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], bus_ofs);
+		if (ret)
+			return ret;
+
+		/* Load 'tmp_buf' with old contents of flash */
+		tmp_buf = map_read(map, bus_ofs + chipstart);
+
+		/* Number of bytes to copy from buffer */
+		n = min_t(int, len, map_bankwidth(map) - i);
+
+		tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n);
+
+		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
+					     bus_ofs, tmp_buf);
+		if (ret)
+			return ret;
+
+		ofs += n;
+		buf += n;
+		(*retlen) += n;
+		len -= n;
+
+		if (ofs >> cfi->chipshift) {
+			chipnum++;
+			ofs = 0;
+			if (chipnum == cfi->numchips)
+				return 0;
+		}
+	}
+
+	/* We are now aligned, write as much as possible */
+	while (len >= map_bankwidth(map)) {
+		map_word datum;
+
+		datum = map_word_load(map, buf);
+
+		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
+					     ofs, datum);
+		if (ret)
+			return ret;
+
+		ofs += map_bankwidth(map);
+		buf += map_bankwidth(map);
+		(*retlen) += map_bankwidth(map);
+		len -= map_bankwidth(map);
+
+		if (ofs >> cfi->chipshift) {
+			chipnum++;
+			ofs = 0;
+			if (chipnum == cfi->numchips)
+				return 0;
+
+			chipstart = cfi->chips[chipnum].start;
+		}
+	}
+
+	/* Write the trailing bytes if any */
+	if (len & (map_bankwidth(map) - 1)) {
+		map_word tmp_buf;
+
+		ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], ofs);
+		if (ret)
+			return ret;
+
+		tmp_buf = map_read(map, ofs + chipstart);
+
+		tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len);
+
+		ret = do_panic_write_oneword(map, &cfi->chips[chipnum],
+					     ofs, tmp_buf);
+		if (ret)
+			return ret;
+
+		(*retlen) += len;
+	}
+
+	return 0;
+}
+
 
 /*
  * Handle devices with one erase region, that only implement
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 37b05c3..98206b0 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -102,6 +102,13 @@ config M25PXX_USE_FAST_READ
 	help
 	  This option enables FAST_READ access supported by ST M25Pxx.
 
+config MTD_SPEAR_SMI
+	tristate "SPEAR MTD NOR Support through SMI controller"
+	depends on PLAT_SPEAR
+	default y
+	help
+	  This enable SNOR support on SPEAR platforms using SMI controller
+
 config MTD_SST25L
 	tristate "Support SST25L (non JEDEC) SPI Flash chips"
 	depends on SPI_MASTER
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index 56c7cd4..a4dd1d8 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MTD_LART)		+= lart.o
 obj-$(CONFIG_MTD_BLOCK2MTD)	+= block2mtd.o
 obj-$(CONFIG_MTD_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
+obj-$(CONFIG_MTD_SPEAR_SMI)	+= spear_smi.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 
 CFLAGS_docg3.o			+= -I$(src)
\ No newline at end of file
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index ecff765..cfccf65 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -359,7 +359,7 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len,
  * mechanism
  * returns the size of the memory region found.
  */
-static u32 fixup_pmc551(struct pci_dev *dev)
+static int fixup_pmc551(struct pci_dev *dev)
 {
 #ifdef CONFIG_MTD_PMC551_BUGFIX
 	u32 dram_data;
@@ -669,7 +669,7 @@ static int __init init_pmc551(void)
 	struct mypriv *priv;
 	int found = 0;
 	struct mtd_info *mtd;
-	u32 length = 0;
+	int length = 0;
 
 	if (msize) {
 		msize = (1 << (ffs(msize) - 1)) << 20;
diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c
new file mode 100644
index 0000000..9303e56
--- /dev/null
+++ b/drivers/mtd/devices/spear_smi.c
@@ -0,0 +1,1114 @@
+/*
+ * linux/drivers/mtd/devices/spear_smi.c
+ *
+ * SMI (Serial Memory Controller) device driver for Serial NOR Flash on
+ * SPEAr platform
+ * The serial nor interface is largely based on drivers/mtd/m25p80.c,
+ * however the SPI interface has been replaced by SMI.
+ *
+ * Copyright (C) 2010 STMicroelectronics.
+ * Ashish Priyadarshi
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spear_smi.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+
+/* max possible slots for serial-nor flash chip in the SMI controller */
+#define MAX_NUM_FLASH_CHIP	4
+
+/* SMI clock rate */
+#define SMI_MAX_CLOCK_FREQ	50000000 /* 50 MHz */
+
+/* MAX time out to safely come out of a erase or write busy conditions */
+#define SMI_PROBE_TIMEOUT	(HZ / 10)
+#define SMI_MAX_TIME_OUT	(3 * HZ)
+
+/* timeout for command completion */
+#define SMI_CMD_TIMEOUT		(HZ / 10)
+
+/* registers of smi */
+#define SMI_CR1		0x0	/* SMI control register 1 */
+#define SMI_CR2		0x4	/* SMI control register 2 */
+#define SMI_SR		0x8	/* SMI status register */
+#define SMI_TR		0xC	/* SMI transmit register */
+#define SMI_RR		0x10	/* SMI receive register */
+
+/* defines for control_reg 1 */
+#define BANK_EN		(0xF << 0)	/* enables all banks */
+#define DSEL_TIME	(0x6 << 4)	/* Deselect time 6 + 1 SMI_CK periods */
+#define SW_MODE		(0x1 << 28)	/* enables SW Mode */
+#define WB_MODE		(0x1 << 29)	/* Write Burst Mode */
+#define FAST_MODE	(0x1 << 15)	/* Fast Mode */
+#define HOLD1		(0x1 << 16)	/* Clock Hold period selection */
+
+/* defines for control_reg 2 */
+#define SEND		(0x1 << 7)	/* Send data */
+#define TFIE		(0x1 << 8)	/* Transmission Flag Interrupt Enable */
+#define WCIE		(0x1 << 9)	/* Write Complete Interrupt Enable */
+#define RD_STATUS_REG	(0x1 << 10)	/* reads status reg */
+#define WE		(0x1 << 11)	/* Write Enable */
+
+#define TX_LEN_SHIFT	0
+#define RX_LEN_SHIFT	4
+#define BANK_SHIFT	12
+
+/* defines for status register */
+#define SR_WIP		0x1	/* Write in progress */
+#define SR_WEL		0x2	/* Write enable latch */
+#define SR_BP0		0x4	/* Block protect 0 */
+#define SR_BP1		0x8	/* Block protect 1 */
+#define SR_BP2		0x10	/* Block protect 2 */
+#define SR_SRWD		0x80	/* SR write protect */
+#define TFF		0x100	/* Transfer Finished Flag */
+#define WCF		0x200	/* Transfer Finished Flag */
+#define ERF1		0x400	/* Forbidden Write Request */
+#define ERF2		0x800	/* Forbidden Access */
+
+#define WM_SHIFT	12
+
+/* flash opcodes */
+#define OPCODE_RDID	0x9f	/* Read JEDEC ID */
+
+/* Flash Device Ids maintenance section */
+
+/* data structure to maintain flash ids from different vendors */
+struct flash_device {
+	char *name;
+	u8 erase_cmd;
+	u32 device_id;
+	u32 pagesize;
+	unsigned long sectorsize;
+	unsigned long size_in_bytes;
+};
+
+#define FLASH_ID(n, es, id, psize, ssize, size)	\
+{				\
+	.name = n,		\
+	.erase_cmd = es,	\
+	.device_id = id,	\
+	.pagesize = psize,	\
+	.sectorsize = ssize,	\
+	.size_in_bytes = size	\
+}
+
+static struct flash_device flash_devices[] = {
+	FLASH_ID("st m25p16"     , 0xd8, 0x00152020, 0x100, 0x10000, 0x200000),
+	FLASH_ID("st m25p32"     , 0xd8, 0x00162020, 0x100, 0x10000, 0x400000),
+	FLASH_ID("st m25p64"     , 0xd8, 0x00172020, 0x100, 0x10000, 0x800000),
+	FLASH_ID("st m25p128"    , 0xd8, 0x00182020, 0x100, 0x40000, 0x1000000),
+	FLASH_ID("st m25p05"     , 0xd8, 0x00102020, 0x80 , 0x8000 , 0x10000),
+	FLASH_ID("st m25p10"     , 0xd8, 0x00112020, 0x80 , 0x8000 , 0x20000),
+	FLASH_ID("st m25p20"     , 0xd8, 0x00122020, 0x100, 0x10000, 0x40000),
+	FLASH_ID("st m25p40"     , 0xd8, 0x00132020, 0x100, 0x10000, 0x80000),
+	FLASH_ID("st m25p80"     , 0xd8, 0x00142020, 0x100, 0x10000, 0x100000),
+	FLASH_ID("st m45pe10"    , 0xd8, 0x00114020, 0x100, 0x10000, 0x20000),
+	FLASH_ID("st m45pe20"    , 0xd8, 0x00124020, 0x100, 0x10000, 0x40000),
+	FLASH_ID("st m45pe40"    , 0xd8, 0x00134020, 0x100, 0x10000, 0x80000),
+	FLASH_ID("st m45pe80"    , 0xd8, 0x00144020, 0x100, 0x10000, 0x100000),
+	FLASH_ID("sp s25fl004"   , 0xd8, 0x00120201, 0x100, 0x10000, 0x80000),
+	FLASH_ID("sp s25fl008"   , 0xd8, 0x00130201, 0x100, 0x10000, 0x100000),
+	FLASH_ID("sp s25fl016"   , 0xd8, 0x00140201, 0x100, 0x10000, 0x200000),
+	FLASH_ID("sp s25fl032"   , 0xd8, 0x00150201, 0x100, 0x10000, 0x400000),
+	FLASH_ID("sp s25fl064"   , 0xd8, 0x00160201, 0x100, 0x10000, 0x800000),
+	FLASH_ID("atmel 25f512"  , 0x52, 0x0065001F, 0x80 , 0x8000 , 0x10000),
+	FLASH_ID("atmel 25f1024" , 0x52, 0x0060001F, 0x100, 0x8000 , 0x20000),
+	FLASH_ID("atmel 25f2048" , 0x52, 0x0063001F, 0x100, 0x10000, 0x40000),
+	FLASH_ID("atmel 25f4096" , 0x52, 0x0064001F, 0x100, 0x10000, 0x80000),
+	FLASH_ID("atmel 25fs040" , 0xd7, 0x0004661F, 0x100, 0x10000, 0x80000),
+	FLASH_ID("mac 25l512"    , 0xd8, 0x001020C2, 0x010, 0x10000, 0x10000),
+	FLASH_ID("mac 25l1005"   , 0xd8, 0x001120C2, 0x010, 0x10000, 0x20000),
+	FLASH_ID("mac 25l2005"   , 0xd8, 0x001220C2, 0x010, 0x10000, 0x40000),
+	FLASH_ID("mac 25l4005"   , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+	FLASH_ID("mac 25l4005a"  , 0xd8, 0x001320C2, 0x010, 0x10000, 0x80000),
+	FLASH_ID("mac 25l8005"   , 0xd8, 0x001420C2, 0x010, 0x10000, 0x100000),
+	FLASH_ID("mac 25l1605"   , 0xd8, 0x001520C2, 0x100, 0x10000, 0x200000),
+	FLASH_ID("mac 25l1605a"  , 0xd8, 0x001520C2, 0x010, 0x10000, 0x200000),
+	FLASH_ID("mac 25l3205"   , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+	FLASH_ID("mac 25l3205a"  , 0xd8, 0x001620C2, 0x100, 0x10000, 0x400000),
+	FLASH_ID("mac 25l6405"   , 0xd8, 0x001720C2, 0x100, 0x10000, 0x800000),
+};
+
+/* These partitions would be used if platform doesn't pass one */
+static struct mtd_partition part_info_8M[] = {
+	DEFINE_PARTS("Xloader", 0x00, 0x10000),
+	DEFINE_PARTS("UBoot", MTDPART_OFS_APPEND, 0x40000),
+	DEFINE_PARTS("Kernel", MTDPART_OFS_APPEND, 0x2C0000),
+	DEFINE_PARTS("Root File System", MTDPART_OFS_APPEND, MTDPART_SIZ_FULL),
+};
+
+static struct mtd_partition part_info_16M[] = {
+	DEFINE_PARTS("Xloader", 0x00, 0x40000),
+	DEFINE_PARTS("UBoot", MTDPART_OFS_APPEND, 0x100000),
+	DEFINE_PARTS("Kernel", MTDPART_OFS_APPEND, 0x300000),
+	DEFINE_PARTS("Root File System", MTDPART_OFS_APPEND, MTDPART_SIZ_FULL),
+};
+
+/* Define spear specific structures */
+
+struct spear_snor_flash;
+
+/**
+ * struct spear_smi - Structure for SMI Device
+ *
+ * @clk: functional clock
+ * @status: current status register of SMI.
+ * @clk_rate: functional clock rate of SMI (default: SMI_MAX_CLOCK_FREQ)
+ * @lock: lock to prevent parallel access of SMI.
+ * @io_base: base address for registers of SMI.
+ * @pdev: platform device
+ * @cmd_complete: queue to wait for command completion of NOR-flash.
+ * @num_flashes: number of flashes actually present on board.
+ * @flash: separate structure for each Serial NOR-flash attached to SMI.
+ */
+struct spear_smi {
+	struct clk *clk;
+	u32 status;
+	unsigned long clk_rate;
+	struct mutex lock;
+	void __iomem *io_base;
+	struct platform_device *pdev;
+	wait_queue_head_t cmd_complete;
+	u32 num_flashes;
+	struct spear_snor_flash *flash[MAX_NUM_FLASH_CHIP];
+};
+
+/**
+ * struct spear_snor_flash - Structure for Serial NOR Flash
+ *
+ * @bank: Bank number(0, 1, 2, 3) for each NOR-flash.
+ * @dev_id: Device ID of NOR-flash.
+ * @lock: lock to manage flash read, write and erase operations
+ * @mtd: MTD info for each NOR-flash.
+ * @num_parts: Total number of partition in each bank of NOR-flash.
+ * @parts: Partition info for each bank of NOR-flash.
+ * @page_size: Page size of NOR-flash.
+ * @base_addr: Base address of NOR-flash.
+ * @erase_cmd: erase command may vary on different flash types
+ * @fast_mode: flash supports read in fast mode
+ */
+struct spear_snor_flash {
+	u32 bank;
+	u32 dev_id;
+	struct mutex lock;
+	struct mtd_info mtd;
+	u32 num_parts;
+	struct mtd_partition *parts;
+	u32 page_size;
+	void __iomem *base_addr;
+	u8 erase_cmd;
+	u8 fast_mode;
+};
+
+static inline struct spear_snor_flash *get_flash_data(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct spear_snor_flash, mtd);
+}
+
+/**
+ * spear_smi_read_sr - Read status register of flash through SMI
+ * @dev: structure of SMI information.
+ * @bank: bank to which flash is connected
+ *
+ * This routine will return the status register of the flash chip present at the
+ * given bank.
+ */
+static int spear_smi_read_sr(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	mutex_lock(&dev->lock);
+	dev->status = 0; /* Will be set in interrupt handler */
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	/* program smi in hw mode */
+	writel(ctrlreg1 & ~(SW_MODE | WB_MODE), dev->io_base + SMI_CR1);
+
+	/* performing a rsr instruction in hw mode */
+	writel((bank << BANK_SHIFT) | RD_STATUS_REG | TFIE,
+			dev->io_base + SMI_CR2);
+
+	/* wait for tff */
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	/* copy dev->status (lower 16 bits) in order to release lock */
+	if (ret > 0)
+		ret = dev->status & 0xffff;
+	else
+		ret = -EIO;
+
+	/* restore the ctrl regs state */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+/**
+ * spear_smi_wait_till_ready - wait till flash is ready
+ * @dev: structure of SMI information.
+ * @bank: flash corresponding to this bank
+ * @timeout: timeout for busy wait condition
+ *
+ * This routine checks for WIP (write in progress) bit in Status register
+ * If successful the routine returns 0 else -EBUSY
+ */
+static int spear_smi_wait_till_ready(struct spear_smi *dev, u32 bank,
+		unsigned long timeout)
+{
+	unsigned long finish;
+	int status;
+
+	finish = jiffies + timeout;
+	do {
+		status = spear_smi_read_sr(dev, bank);
+		if (status < 0)
+			continue; /* try till timeout */
+		else if (!(status & SR_WIP))
+			return 0;
+
+		cond_resched();
+	} while (!time_after_eq(jiffies, finish));
+
+	dev_err(&dev->pdev->dev, "smi controller is busy, timeout\n");
+	return status;
+}
+
+/**
+ * spear_smi_int_handler - SMI Interrupt Handler.
+ * @irq: irq number
+ * @dev_id: structure of SMI device, embedded in dev_id.
+ *
+ * The handler clears all interrupt conditions and records the status in
+ * dev->status which is used by the driver later.
+ */
+static irqreturn_t spear_smi_int_handler(int irq, void *dev_id)
+{
+	u32 status = 0;
+	struct spear_smi *dev = dev_id;
+
+	status = readl(dev->io_base + SMI_SR);
+
+	if (unlikely(!status))
+		return IRQ_NONE;
+
+	/* clear all interrupt conditions */
+	writel(0, dev->io_base + SMI_SR);
+
+	/* copy the status register in dev->status */
+	dev->status |= status;
+
+	/* send the completion */
+	wake_up_interruptible(&dev->cmd_complete);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * spear_smi_hw_init - initializes the smi controller.
+ * @dev: structure of smi device
+ *
+ * this routine initializes the smi controller wit the default values
+ */
+static void spear_smi_hw_init(struct spear_smi *dev)
+{
+	unsigned long rate = 0;
+	u32 prescale = 0;
+	u32 val;
+
+	rate = clk_get_rate(dev->clk);
+
+	/* functional clock of smi */
+	prescale = DIV_ROUND_UP(rate, dev->clk_rate);
+
+	/*
+	 * setting the standard values, fast mode, prescaler for
+	 * SMI_MAX_CLOCK_FREQ (50MHz) operation and bank enable
+	 */
+	val = HOLD1 | BANK_EN | DSEL_TIME | (prescale << 8);
+
+	mutex_lock(&dev->lock);
+	writel(val, dev->io_base + SMI_CR1);
+	mutex_unlock(&dev->lock);
+}
+
+/**
+ * get_flash_index - match chip id from a flash list.
+ * @flash_id: a valid nor flash chip id obtained from board.
+ *
+ * try to validate the chip id by matching from a list, if not found then simply
+ * returns negative. In case of success returns index in to the flash devices
+ * array.
+ */
+static int get_flash_index(u32 flash_id)
+{
+	int index;
+
+	/* Matches chip-id to entire list of 'serial-nor flash' ids */
+	for (index = 0; index < ARRAY_SIZE(flash_devices); index++) {
+		if (flash_devices[index].device_id == flash_id)
+			return index;
+	}
+
+	/* Memory chip is not listed and not supported */
+	return -ENODEV;
+}
+
+/**
+ * spear_smi_write_enable - Enable the flash to do write operation
+ * @dev: structure of SMI device
+ * @bank: enable write for flash connected to this bank
+ *
+ * Set write enable latch with Write Enable command.
+ * Returns 0 on success.
+ */
+static int spear_smi_write_enable(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	mutex_lock(&dev->lock);
+	dev->status = 0; /* Will be set in interrupt handler */
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	/* program smi in h/w mode */
+	writel(ctrlreg1 & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	/* give the flash, write enable command */
+	writel((bank << BANK_SHIFT) | WE | TFIE, dev->io_base + SMI_CR2);
+
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	/* restore the ctrl regs state */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+
+	if (ret <= 0) {
+		ret = -EIO;
+		dev_err(&dev->pdev->dev,
+			"smi controller failed on write enable\n");
+	} else {
+		/* check whether write mode status is set for required bank */
+		if (dev->status & (1 << (bank + WM_SHIFT)))
+			ret = 0;
+		else {
+			dev_err(&dev->pdev->dev, "couldn't enable write\n");
+			ret = -EIO;
+		}
+	}
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static inline u32
+get_sector_erase_cmd(struct spear_snor_flash *flash, u32 offset)
+{
+	u32 cmd;
+	u8 *x = (u8 *)&cmd;
+
+	x[0] = flash->erase_cmd;
+	x[1] = offset >> 16;
+	x[2] = offset >> 8;
+	x[3] = offset;
+
+	return cmd;
+}
+
+/**
+ * spear_smi_erase_sector - erase one sector of flash
+ * @dev: structure of SMI information
+ * @command: erase command to be send
+ * @bank: bank to which this command needs to be send
+ * @bytes: size of command
+ *
+ * Erase one sector of flash memory at offset ``offset'' which is any
+ * address within the sector which should be erased.
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int spear_smi_erase_sector(struct spear_smi *dev,
+		u32 bank, u32 command, u32 bytes)
+{
+	u32 ctrlreg1 = 0;
+	int ret;
+
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_MAX_TIME_OUT);
+	if (ret)
+		return ret;
+
+	ret = spear_smi_write_enable(dev, bank);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->lock);
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	writel((ctrlreg1 | SW_MODE) & ~WB_MODE, dev->io_base + SMI_CR1);
+
+	/* send command in sw mode */
+	writel(command, dev->io_base + SMI_TR);
+
+	writel((bank << BANK_SHIFT) | SEND | TFIE | (bytes << TX_LEN_SHIFT),
+			dev->io_base + SMI_CR2);
+
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+
+	if (ret <= 0) {
+		ret = -EIO;
+		dev_err(&dev->pdev->dev, "sector erase failed\n");
+	} else
+		ret = 0; /* success */
+
+	/* restore ctrl regs */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	writel(0, dev->io_base + SMI_CR2);
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+/**
+ * spear_mtd_erase - perform flash erase operation as requested by user
+ * @mtd: Provides the memory characteristics
+ * @e_info: Provides the erase information
+ *
+ * Erase an address range on the flash chip. The address range may extend
+ * one or more erase sectors. Return an error is there is a problem erasing.
+ */
+static int spear_mtd_erase(struct mtd_info *mtd, struct erase_info *e_info)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	u32 addr, command, bank;
+	int len, ret;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	/* do not allow erase past end of device */
+	if (e_info->addr + e_info->len > flash->mtd.size)
+		return -EINVAL;
+
+	bank = flash->bank;
+	if (bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	addr = e_info->addr;
+	len = e_info->len;
+
+	mutex_lock(&flash->lock);
+
+	/* now erase sectors in loop */
+	while (len) {
+		command = get_sector_erase_cmd(flash, addr);
+		/* preparing the command for flash */
+		ret = spear_smi_erase_sector(dev, bank, command, 4);
+		if (ret) {
+			e_info->state = MTD_ERASE_FAILED;
+			mutex_unlock(&flash->lock);
+			return ret;
+		}
+		addr += mtd->erasesize;
+		len -= mtd->erasesize;
+	}
+
+	mutex_unlock(&flash->lock);
+	e_info->state = MTD_ERASE_DONE;
+	mtd_erase_callback(e_info);
+
+	return 0;
+}
+
+/**
+ * spear_mtd_read - performs flash read operation as requested by the user
+ * @mtd: MTD information of the memory bank
+ * @from: Address from which to start read
+ * @len: Number of bytes to be read
+ * @retlen: Fills the Number of bytes actually read
+ * @buf: Fills this after reading
+ *
+ * Read an address range from the flash chip. The address range
+ * may be any size provided it is within the physical boundaries.
+ * Returns 0 on success, non zero otherwise
+ */
+static int spear_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u8 *buf)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	void *src;
+	u32 ctrlreg1, val;
+	int ret;
+
+	if (!len)
+		return 0;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	/* do not allow reads past end of device */
+	if (from + len > flash->mtd.size)
+		return -EINVAL;
+
+	if (flash->bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	if (!retlen)
+		return -EINVAL;
+	else
+		*retlen = 0;
+
+	/* select address as per bank number */
+	src = flash->base_addr + from;
+
+	mutex_lock(&flash->lock);
+
+	/* wait till previous write/erase is done. */
+	ret = spear_smi_wait_till_ready(dev, flash->bank, SMI_MAX_TIME_OUT);
+	if (ret) {
+		mutex_unlock(&flash->lock);
+		return ret;
+	}
+
+	mutex_lock(&dev->lock);
+	/* put smi in hw mode not wbt mode */
+	ctrlreg1 = val = readl(dev->io_base + SMI_CR1);
+	val &= ~(SW_MODE | WB_MODE);
+	if (flash->fast_mode)
+		val |= FAST_MODE;
+
+	writel(val, dev->io_base + SMI_CR1);
+
+	memcpy_fromio(buf, (u8 *)src, len);
+
+	/* restore ctrl reg1 */
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+	mutex_unlock(&dev->lock);
+
+	*retlen = len;
+	mutex_unlock(&flash->lock);
+
+	return 0;
+}
+
+static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
+		void *dest, const void *src, size_t len)
+{
+	int ret;
+	u32 ctrlreg1;
+
+	/* wait until finished previous write command. */
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_MAX_TIME_OUT);
+	if (ret)
+		return ret;
+
+	/* put smi in write enable */
+	ret = spear_smi_write_enable(dev, bank);
+	if (ret)
+		return ret;
+
+	/* put smi in hw, write burst mode */
+	mutex_lock(&dev->lock);
+
+	ctrlreg1 = readl(dev->io_base + SMI_CR1);
+	writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	memcpy_toio(dest, src, len);
+
+	writel(ctrlreg1, dev->io_base + SMI_CR1);
+
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+/**
+ * spear_mtd_write - performs write operation as requested by the user.
+ * @mtd: MTD information of the memory bank.
+ * @to:	Address to write.
+ * @len: Number of bytes to be written.
+ * @retlen: Number of bytes actually wrote.
+ * @buf: Buffer from which the data to be taken.
+ *
+ * Write an address range to the flash chip. Data must be written in
+ * flash_page_size chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ * Returns 0 on success, non zero otherwise
+ */
+static int spear_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
+		size_t *retlen, const u8 *buf)
+{
+	struct spear_snor_flash *flash = get_flash_data(mtd);
+	struct spear_smi *dev = mtd->priv;
+	void *dest;
+	u32 page_offset, page_size;
+	int ret;
+
+	if (!flash || !dev)
+		return -ENODEV;
+
+	if (!len)
+		return 0;
+
+	/* do not allow write past end of page */
+	if (to + len > flash->mtd.size)
+		return -EINVAL;
+
+	if (flash->bank > dev->num_flashes - 1) {
+		dev_err(&dev->pdev->dev, "Invalid Bank Num");
+		return -EINVAL;
+	}
+
+	if (!retlen)
+		return -EINVAL;
+	else
+		*retlen = 0;
+
+	/* select address as per bank number */
+	dest = flash->base_addr + to;
+	mutex_lock(&flash->lock);
+
+	page_offset = (u32)to % flash->page_size;
+
+	/* do if all the bytes fit onto one page */
+	if (page_offset + len <= flash->page_size) {
+		ret = spear_smi_cpy_toio(dev, flash->bank, dest, buf, len);
+		if (!ret)
+			*retlen += len;
+	} else {
+		u32 i;
+
+		/* the size of data remaining on the first page */
+		page_size = flash->page_size - page_offset;
+
+		ret = spear_smi_cpy_toio(dev, flash->bank, dest, buf,
+				page_size);
+		if (ret)
+			goto err_write;
+		else
+			*retlen += page_size;
+
+		/* write everything in pagesize chunks */
+		for (i = page_size; i < len; i += page_size) {
+			page_size = len - i;
+			if (page_size > flash->page_size)
+				page_size = flash->page_size;
+
+			ret = spear_smi_cpy_toio(dev, flash->bank, dest + i,
+					buf + i, page_size);
+			if (ret)
+				break;
+			else
+				*retlen += page_size;
+		}
+	}
+
+err_write:
+	mutex_unlock(&flash->lock);
+
+	return ret;
+}
+
+/**
+ * spear_smi_probe_flash - Detects the NOR Flash chip.
+ * @dev: structure of SMI information.
+ * @bank: bank on which flash must be probed
+ *
+ * This routine will check whether there exists a flash chip on a given memory
+ * bank ID.
+ * Return index of the probed flash in flash devices structure
+ */
+static int spear_smi_probe_flash(struct spear_smi *dev, u32 bank)
+{
+	int ret;
+	u32 val = 0;
+
+	ret = spear_smi_wait_till_ready(dev, bank, SMI_PROBE_TIMEOUT);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->lock);
+
+	dev->status = 0; /* Will be set in interrupt handler */
+	/* put smi in sw mode */
+	val = readl(dev->io_base + SMI_CR1);
+	writel(val | SW_MODE, dev->io_base + SMI_CR1);
+
+	/* send readid command in sw mode */
+	writel(OPCODE_RDID, dev->io_base + SMI_TR);
+
+	val = (bank << BANK_SHIFT) | SEND | (1 << TX_LEN_SHIFT) |
+		(3 << RX_LEN_SHIFT) | TFIE;
+	writel(val, dev->io_base + SMI_CR2);
+
+	/* wait for TFF */
+	ret = wait_event_interruptible_timeout(dev->cmd_complete,
+			dev->status & TFF, SMI_CMD_TIMEOUT);
+	if (ret <= 0) {
+		ret = -ENODEV;
+		goto err_probe;
+	}
+
+	/* get memory chip id */
+	val = readl(dev->io_base + SMI_RR);
+	val &= 0x00ffffff;
+	ret = get_flash_index(val);
+
+err_probe:
+	/* clear sw mode */
+	val = readl(dev->io_base + SMI_CR1);
+	writel(val & ~SW_MODE, dev->io_base + SMI_CR1);
+
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static int spear_smi_setup_banks(struct platform_device *pdev, u32 bank)
+{
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+	struct spear_smi_flash_info *flash_info;
+	struct spear_smi_plat_data *pdata;
+	struct spear_snor_flash *flash;
+	struct mtd_partition *parts;
+	int count;
+	int flash_index;
+	int ret = 0;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (bank > pdata->num_flashes - 1)
+		return -EINVAL;
+
+	flash_info = &pdata->board_flash_info[bank];
+	if (!flash_info)
+		return -ENODEV;
+
+	flash = kzalloc(sizeof(*flash), GFP_ATOMIC);
+	if (!flash)
+		return -ENOMEM;
+	flash->bank = bank;
+	flash->fast_mode = flash_info->fast_mode ? 1 : 0;
+	mutex_init(&flash->lock);
+
+	/* verify whether nor flash is really present on board */
+	flash_index = spear_smi_probe_flash(dev, bank);
+	if (flash_index < 0) {
+		dev_info(&dev->pdev->dev, "smi-nor%d not found\n", bank);
+		ret = flash_index;
+		goto err_probe;
+	}
+	/* map the memory for nor flash chip */
+	flash->base_addr = ioremap(flash_info->mem_base, flash_info->size);
+	if (!flash->base_addr) {
+		ret = -EIO;
+		goto err_probe;
+	}
+
+	dev->flash[bank] = flash;
+	flash->mtd.priv = dev;
+
+	if (flash_info->name)
+		flash->mtd.name = flash_info->name;
+	else
+		flash->mtd.name = flash_devices[flash_index].name;
+
+	flash->mtd.type = MTD_NORFLASH;
+	flash->mtd.writesize = 1;
+	flash->mtd.flags = MTD_CAP_NORFLASH;
+	flash->mtd.size = flash_info->size;
+	flash->mtd.erasesize = flash_devices[flash_index].sectorsize;
+	flash->page_size = flash_devices[flash_index].pagesize;
+	flash->erase_cmd = flash_devices[flash_index].erase_cmd;
+	flash->mtd.erase = spear_mtd_erase;
+	flash->mtd.read = spear_mtd_read;
+	flash->mtd.write = spear_mtd_write;
+	flash->dev_id = flash_devices[flash_index].device_id;
+
+	dev_info(&dev->pdev->dev, "mtd .name=%s .size=%llx(%lluM)\n",
+			flash->mtd.name, flash->mtd.size,
+			flash->mtd.size / (1024 * 1024));
+
+	dev_info(&dev->pdev->dev, ".erasesize = 0x%x(%uK)\n",
+			flash->mtd.erasesize, flash->mtd.erasesize / 1024);
+
+	if (flash_info->partitions) {
+		parts = flash_info->partitions;
+		count = flash_info->nr_partitions;
+	} else {
+		/* choose from default ones */
+		switch (flash->mtd.size) {
+		case 0x800000:/* 8MB */
+			parts = part_info_8M;
+			count = ARRAY_SIZE(part_info_8M);
+			break;
+		case 0x1000000:/* 16MB */
+			parts = part_info_16M;
+			count = ARRAY_SIZE(part_info_16M);
+			break;
+		default:
+			dev_err(&pdev->dev, "undefined partition\n");
+			ret = ENODEV;
+			goto err_map;
+		}
+	}
+	ret = mtd_device_parse_register(&flash->mtd, NULL, 0, parts, count);
+	if (ret)
+		dev_err(&dev->pdev->dev, "Err MTD partition=%d\n", ret);
+
+	return ret;
+
+err_map:
+	iounmap(flash->base_addr);
+
+err_probe:
+	kfree(flash);
+	return ret;
+}
+
+/**
+ * spear_smi_probe - Entry routine
+ * @pdev: platform device structure
+ *
+ * This is the first routine which gets invoked during booting and does all
+ * initialization/allocation work. The routine looks for available memory banks,
+ * and do proper init for any found one.
+ * Returns 0 on success, non zero otherwise
+ */
+static int __devinit spear_smi_probe(struct platform_device *pdev)
+{
+	struct spear_smi_plat_data *pdata;
+	struct spear_smi *dev;
+	struct resource *smi_base;
+	int irq, ret = 0;
+	int i;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata < 0) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "no platform data\n");
+		goto err;
+	}
+
+	smi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!smi_base) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "invalid smi base address\n");
+		goto err;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev, "invalid smi irq\n");
+		goto err;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_ATOMIC);
+	if (!dev) {
+		ret = -ENOMEM;
+		dev_err(&pdev->dev, "mem alloc fail\n");
+		goto err;
+	}
+
+	smi_base = request_mem_region(smi_base->start, resource_size(smi_base),
+			pdev->name);
+	if (!smi_base) {
+		ret = -EBUSY;
+		dev_err(&pdev->dev, "request mem region fail\n");
+		goto err_mem;
+	}
+
+	dev->io_base = ioremap(smi_base->start, resource_size(smi_base));
+	if (!dev->io_base) {
+		ret = -EIO;
+		dev_err(&pdev->dev, "ioremap fail\n");
+		goto err_ioremap;
+	}
+
+	dev->pdev = pdev;
+	dev->clk_rate = pdata->clk_rate;
+
+	if (dev->clk_rate < 0 || dev->clk_rate > SMI_MAX_CLOCK_FREQ)
+		dev->clk_rate = SMI_MAX_CLOCK_FREQ;
+
+	dev->num_flashes = pdata->num_flashes;
+
+	if (dev->num_flashes > MAX_NUM_FLASH_CHIP) {
+		dev_err(&pdev->dev, "exceeding max number of flashes\n");
+		dev->num_flashes = MAX_NUM_FLASH_CHIP;
+	}
+
+	dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		ret = PTR_ERR(dev->clk);
+		goto err_clk;
+	}
+
+	ret = clk_enable(dev->clk);
+	if (ret)
+		goto err_clk_enable;
+
+	ret = request_irq(irq, spear_smi_int_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&dev->pdev->dev, "SMI IRQ allocation failed\n");
+		goto err_irq;
+	}
+
+	mutex_init(&dev->lock);
+	init_waitqueue_head(&dev->cmd_complete);
+	spear_smi_hw_init(dev);
+	platform_set_drvdata(pdev, dev);
+
+	/* loop for each serial nor-flash which is connected to smi */
+	for (i = 0; i < dev->num_flashes; i++) {
+		ret = spear_smi_setup_banks(pdev, i);
+		if (ret) {
+			dev_err(&dev->pdev->dev, "bank setup failed\n");
+			goto err_bank_setup;
+		}
+	}
+
+	return 0;
+
+err_bank_setup:
+	free_irq(irq, dev);
+	platform_set_drvdata(pdev, NULL);
+err_irq:
+	clk_disable(dev->clk);
+err_clk_enable:
+	clk_put(dev->clk);
+err_clk:
+	iounmap(dev->io_base);
+err_ioremap:
+	release_mem_region(smi_base->start, resource_size(smi_base));
+err_mem:
+	kfree(dev);
+err:
+	return ret;
+}
+
+/**
+ * spear_smi_remove - Exit routine
+ * @pdev: platform device structure
+ *
+ * free all allocations and delete the partitions.
+ */
+static int __devexit spear_smi_remove(struct platform_device *pdev)
+{
+	struct spear_smi *dev;
+	struct spear_snor_flash *flash;
+	int ret;
+	int i, irq;
+
+	dev = platform_get_drvdata(pdev);
+	if (!dev) {
+		dev_err(&pdev->dev, "dev is null\n");
+		return -ENODEV;
+	}
+
+	/* clean up for all nor flash */
+	for (i = 0; i < dev->num_flashes; i++) {
+		flash = dev->flash[i];
+		if (!flash)
+			continue;
+
+		/* clean up mtd stuff */
+		ret = mtd_device_unregister(&flash->mtd);
+		if (ret)
+			dev_err(&pdev->dev, "error removing mtd\n");
+
+		iounmap(flash->base_addr);
+		kfree(flash);
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, dev);
+
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	iounmap(dev->io_base);
+	kfree(dev);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+int spear_smi_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+
+	if (dev && dev->clk)
+		clk_disable(dev->clk);
+
+	return 0;
+}
+
+int spear_smi_resume(struct platform_device *pdev)
+{
+	struct spear_smi *dev = platform_get_drvdata(pdev);
+	int ret = -EPERM;
+
+	if (dev && dev->clk)
+		ret = clk_enable(dev->clk);
+
+	if (!ret)
+		spear_smi_hw_init(dev);
+	return ret;
+}
+
+static struct platform_driver spear_smi_driver = {
+	.driver = {
+		.name = "smi",
+		.bus = &platform_bus_type,
+		.owner = THIS_MODULE,
+	},
+	.probe = spear_smi_probe,
+	.remove = __devexit_p(spear_smi_remove),
+	.suspend = spear_smi_suspend,
+	.resume = spear_smi_resume,
+};
+
+static int spear_smi_init(void)
+{
+	return platform_driver_register(&spear_smi_driver);
+}
+module_init(spear_smi_init);
+
+static void spear_smi_exit(void)
+{
+	platform_driver_unregister(&spear_smi_driver);
+}
+module_exit(spear_smi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim <shiraz.hashim@st.com>");
+MODULE_DESCRIPTION("MTD SMI driver for serial nor flash chips");
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 424ca5f..f1f0671 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -233,6 +233,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
 	ret = __get_mtd_device(dev->mtd);
 	if (ret)
 		goto error_release;
+	dev->file_mode = mode;
 
 unlock:
 	dev->open++;
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index af65912..6c6d807 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -321,8 +321,12 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 	mutex_unlock(&mtdblk->cache_mutex);
 
 	if (!--mtdblk->count) {
-		/* It was the last usage. Free the cache */
-		mtd_sync(mbd->mtd);
+		/*
+		 * It was the last usage. Free the cache, but only sync if
+		 * opened for writing.
+		 */
+		if (mbd->file_mode & FMODE_WRITE)
+			mtd_sync(mbd->mtd);
 		vfree(mtdblk->cache_data);
 	}
 
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6ae9ca0..de96865 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -107,7 +107,7 @@ static LIST_HEAD(mtd_notifiers);
  */
 static void mtd_release(struct device *dev)
 {
-	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct mtd_info __maybe_unused *mtd = dev_get_drvdata(dev);
 	dev_t index = MTD_DEVT(mtd->index);
 
 	/* remove /dev/mtdXro node if needed */
@@ -119,7 +119,7 @@ static int mtd_cls_suspend(struct device *dev, pm_message_t state)
 {
 	struct mtd_info *mtd = dev_get_drvdata(dev);
 
-	return mtd_suspend(mtd);
+	return mtd ? mtd_suspend(mtd) : 0;
 }
 
 static int mtd_cls_resume(struct device *dev)
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 7f68042..7db6555 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask)
  *  [1] enable the module.
  *  [2] reset the module.
  *
- * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
  * If you try to soft reset the BCH block, it becomes unusable until
  * the next hard reset. This case occurs in the NAND boot mode. When the board
  * boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
  * So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
  *
  * To avoid this bug, just add a new parameter `just_enable` for
  * the mxs_reset_block(), and rewrite it here.
  */
-int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
 {
 	int ret;
 	int timeout = 0x400;
@@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this)
 	if (ret)
 		goto err_out;
 
-	ret = gpmi_reset_block(r->bch_regs, true);
+	/*
+	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+	* chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+	* On the other hand, the MX28 needs the reset, because one case has been
+	* seen where the BCH produced ECC errors constantly after 10000
+	* consecutive reboots. The latter case has not been seen on the MX23 yet,
+	* still we don't know if it could happen there as well.
+	*/
+	ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
 	if (ret)
 		goto err_out;
 
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 35b4565..c6603d4 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -338,7 +338,7 @@ static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
  */
 static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 {
-	int page, chipnr, res = 0;
+	int page, chipnr, res = 0, i = 0;
 	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
@@ -356,23 +356,29 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 		chip->select_chip(mtd, chipnr);
 	}
 
-	if (chip->options & NAND_BUSWIDTH_16) {
-		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
-			      page);
-		bad = cpu_to_le16(chip->read_word(mtd));
-		if (chip->badblockpos & 0x1)
-			bad >>= 8;
-		else
-			bad &= 0xFF;
-	} else {
-		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, page);
-		bad = chip->read_byte(mtd);
-	}
+	do {
+		if (chip->options & NAND_BUSWIDTH_16) {
+			chip->cmdfunc(mtd, NAND_CMD_READOOB,
+					chip->badblockpos & 0xFE, page);
+			bad = cpu_to_le16(chip->read_word(mtd));
+			if (chip->badblockpos & 0x1)
+				bad >>= 8;
+			else
+				bad &= 0xFF;
+		} else {
+			chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
+					page);
+			bad = chip->read_byte(mtd);
+		}
 
-	if (likely(chip->badblockbits == 8))
-		res = bad != 0xFF;
-	else
-		res = hweight8(bad) < chip->badblockbits;
+		if (likely(chip->badblockbits == 8))
+			res = bad != 0xFF;
+		else
+			res = hweight8(bad) < chip->badblockbits;
+		ofs += mtd->writesize;
+		page = (int)(ofs >> chip->page_shift) & chip->pagemask;
+		i++;
+	} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
 
 	if (getchip)
 		nand_release_device(mtd);
@@ -394,6 +400,17 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	uint8_t buf[2] = { 0, 0 };
 	int block, ret, i = 0;
 
+	if (!(chip->bbt_options & NAND_BBT_USE_FLASH)) {
+		struct erase_info einfo;
+
+		/* Attempt erase before marking OOB */
+		memset(&einfo, 0, sizeof(einfo));
+		einfo.mtd = mtd;
+		einfo.addr = ofs;
+		einfo.len = 1 << chip->phys_erase_shift;
+		nand_erase_nand(mtd, &einfo, 0);
+	}
+
 	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
 		ofs += mtd->erasesize - mtd->writesize;
 
@@ -413,13 +430,17 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 		/*
 		 * Write to first two pages if necessary. If we write to more
 		 * than one location, the first error encountered quits the
-		 * procedure. We write two bytes per location, so we dont have
-		 * to mess with 16 bit access.
+		 * procedure.
 		 */
-		ops.len = ops.ooblen = 2;
 		ops.datbuf = NULL;
 		ops.oobbuf = buf;
-		ops.ooboffs = chip->badblockpos & ~0x01;
+		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;
 		do {
 			ret = nand_do_write_oob(mtd, ofs, &ops);
@@ -2588,7 +2609,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 	instr->state = MTD_ERASING;
 
 	while (len) {
-		/* Heck if we have a bad block, we do not erase bad blocks! */
+		/* Check if we have a bad block, we do not erase bad blocks! */
 		if (nand_block_checkbad(mtd, ((loff_t) page) <<
 					chip->page_shift, 0, allowbbt)) {
 			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index fa1ee43..deaf762 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -923,7 +923,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		if (!r) {
 			dev_err(&pdev->dev, "no buffer memory resource defined\n");
-			return -ENOENT;
+			err = -ENOENT;
 			goto ahb_resource_failed;
 		}
 
@@ -964,7 +964,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 		r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		if (!r) {
 			dev_err(&pdev->dev, "no dma memory resource defined\n");
-			return -ENOENT;
+			err = -ENOENT;
 			goto dma_resource_failed;
 		}
 
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 342626f..f820b26 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -909,16 +909,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
 	}
 }
 
-/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the device as well as the hw address of the
- * net_device
- */
-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
 {
 	struct net_device *dev = slave->dev;
 	struct sockaddr s_addr;
 
-	if (!hw) {
+	if (slave->bond->params.mode == BOND_MODE_TLB) {
 		memcpy(dev->dev_addr, addr, dev->addr_len);
 		return 0;
 	}
@@ -948,8 +944,8 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct
 	u8 tmp_mac_addr[ETH_ALEN];
 
 	memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
-	alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
-	alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+	alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
+	alb_set_slave_mac_addr(slave2, tmp_mac_addr);
 
 }
 
@@ -1096,8 +1092,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 
 		/* Try setting slave mac to bond address and fall-through
 		   to code handling that situation below... */
-		alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
-				       bond->alb_info.rlb_enabled);
+		alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
 	}
 
 	/* The slave's address is equal to the address of the bond.
@@ -1133,8 +1128,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
 	}
 
 	if (free_mac_slave) {
-		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
-				       bond->alb_info.rlb_enabled);
+		alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
 
 		pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
 			   bond->dev->name, slave->dev->name,
@@ -1491,8 +1485,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
 {
 	int res;
 
-	res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
-				     bond->alb_info.rlb_enabled);
+	res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
 	if (res) {
 		return res;
 	}
@@ -1643,8 +1636,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
 		alb_swap_mac_addr(bond, swap_slave, new_slave);
 	} else {
 		/* set the new_slave to the bond mac address */
-		alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
-				       bond->alb_info.rlb_enabled);
+		alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
 	}
 
 	if (swap_slave) {
@@ -1704,8 +1696,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
 		alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
 		alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
 	} else {
-		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
-				       bond->alb_info.rlb_enabled);
+		alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
 
 		read_lock(&bond->lock);
 		alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index abf4d7a..54364de 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -47,3 +47,13 @@ config CAIF_HSI
        The caif low level driver for CAIF over HSI.
        Be aware that if you enable this then you also need to
        enable a low-level HSI driver.
+
+config CAIF_XSHM
+	tristate "CAIF external memory protocol driver"
+	depends on XSHM_BUS && CAIF
+	default n
+	---help---
+	Say "Y" if you want to support CAIF over External Shared Memory (XSHM)
+	IPC mechanism (e.g. over Chip to Chip). Only say M here if you want to
+	test CAIF over XSHM and need to load and unload its module.
+	If unsure say N.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index 91dff86..9310b24 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
 # Shared memory
 caif_shm-objs := caif_shmcore.o caif_shm_u5500.o
 obj-$(CONFIG_CAIF_SHM) += caif_shm.o
+obj-$(CONFIG_CAIF_XSHM) += caif_xshm.o
 
 # HSI interface
 obj-$(CONFIG_CAIF_HSI) += caif_hsi.o
diff --git a/drivers/net/caif/caif_xshm.c b/drivers/net/caif/caif_xshm.c
new file mode 100644
index 0000000..21ff087
--- /dev/null
+++ b/drivers/net/caif/caif_xshm.c
@@ -0,0 +1,915 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Contact: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * Authors: Sjur Brændeland / sjur.brandeland@stericsson.com
+ *	   Daniel Martensson / daniel.martensson@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s() :" fmt, __func__
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/xshm/xshm_dev.h>
+#include <net/rtnetlink.h>
+#include <net/caif/caif_device.h>
+#include <net/caif/caif_layer.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Daniel Martensson <daniel.martensson@stericsson.com>");
+MODULE_AUTHOR("Sjur Brændeland <sjur.brandeland@stericsson.com>");
+MODULE_DESCRIPTION("CAIF SHM driver");
+
+#define CONNECT_TIMEOUT (3 * HZ)
+#define CAIF_NEEDED_HEADROOM	32
+#define CAIF_FLOW_ON		1
+#define CAIF_FLOW_OFF		0
+
+#define LOW_XOFF_WATERMARK	50
+#define HIGH_XOFF_WATERMARK	70
+#define STUFF_MARK		30
+
+struct ringbuf {
+	__le32	*rip;
+	__le32	*wip;
+	u32	size;
+	__le32	*bufsize;
+};
+
+struct shm_pck_desc {
+	/* Offset from start of channel to CAIF frame. */
+	u32 offset;
+	u32 length;
+} __packed;
+
+struct shm_caif_frm {
+	/* Number of bytes of padding before the CAIF frame. */
+	u8 hdr_ofs;
+} __packed;
+
+#define SHM_HDR_LEN sizeof(struct shm_caif_frm)
+
+struct shmbuffer {
+/* Static part: */
+	u8 *addr;
+	u32 index;
+	u32 len;
+/* Dynamic part: */
+	u32 frames;
+	/* Offset from start of buffer to CAIF frame. */
+	u32 frm_ofs;
+};
+
+enum CFSHM_STATE {
+	CFSHM_CLOSED = 1,
+	CFSHM_OPENING,
+	CFSHM_OPEN
+};
+
+struct cfshm {
+	/* caif_dev_common must always be first in the structure*/
+	struct caif_dev_common cfdev;
+	struct xshm_dev *xshm;
+	struct napi_struct napi;
+	struct ringbuf tx;
+	struct sk_buff_head sk_qhead;
+	spinlock_t lock;
+	struct ringbuf rx;
+	u8 *rx_ringbuf;
+	u32 rx_frms_pr_buf;
+	u32 rx_alignment;
+	struct shmbuffer **rx_bufs;
+	struct net_device *ndev;
+
+	u32 tx_frms_pr_buf;
+	u32 tx_alignment;
+	struct shmbuffer **tx_bufs;
+	u8 *tx_ringbuf;
+	u32 tx_flow_on;
+	u32 high_xoff_water;
+	u32 low_xoff_water;
+	u32 stuff_mark;
+	atomic_t dbg_smp_rxactive;
+	enum CFSHM_STATE state;
+	wait_queue_head_t netmgmt_wq;
+};
+
+static unsigned int ringbuf_used(struct ringbuf *rb)
+{
+	if (le32_to_cpu(*rb->wip) >= le32_to_cpu(*rb->rip))
+		return le32_to_cpu(*rb->wip) - le32_to_cpu(*rb->rip);
+	else
+		return rb->size - le32_to_cpu(*rb->rip) + le32_to_cpu(*rb->wip);
+}
+
+static int ringbuf_get_writepos(struct ringbuf *rb)
+{
+	if ((le32_to_cpu(*rb->wip) + 1) % rb->size == le32_to_cpu(*rb->rip))
+		return -1;
+	else
+		return le32_to_cpu(*rb->wip);
+}
+
+static int ringbuf_get_readpos(struct ringbuf *rb)
+{
+
+	if (le32_to_cpu(*rb->wip) == le32_to_cpu(*rb->rip))
+		return -1;
+	else
+		return le32_to_cpu(*rb->rip);
+}
+
+static int ringbuf_upd_writeptr(struct ringbuf *rb)
+{
+	if (!WARN_ON((le32_to_cpu(*rb->wip) + 1) % rb->size ==
+					le32_to_cpu(*rb->rip))) {
+
+		*rb->wip = cpu_to_le32((le32_to_cpu(*rb->wip) + 1) % rb->size);
+		/* Do write barrier before updating index */
+		smp_wmb();
+	}
+	return le32_to_cpu(*rb->wip);
+}
+
+static void ringbuf_upd_readptr(struct ringbuf *rb)
+{
+	if (!WARN_ON(le32_to_cpu(*rb->wip) == le32_to_cpu(*rb->rip))) {
+		*rb->rip = cpu_to_le32((le32_to_cpu(*rb->rip) + 1) % rb->size);
+		/* Do write barrier before updating index */
+		smp_wmb();
+	}
+}
+
+
+
+static struct shmbuffer *get_rx_buf(struct cfshm *cfshm)
+{
+	struct shmbuffer *pbuf = NULL;
+	int idx = ringbuf_get_readpos(&cfshm->rx);
+
+	if (idx < 0)
+		goto out;
+	pbuf = cfshm->rx_bufs[idx];
+out:
+	return pbuf;
+}
+
+static struct shmbuffer *new_rx_buf(struct cfshm *cfshm)
+{
+	struct shmbuffer *pbuf = get_rx_buf(cfshm);
+
+	WARN_ON(!spin_is_locked(&cfshm->lock));
+	if (pbuf)
+		pbuf->frames = 0;
+
+	return pbuf;
+}
+
+static struct shmbuffer *get_tx_buf(struct cfshm *cfshm)
+{
+	int idx = ringbuf_get_writepos(&cfshm->tx);
+
+	if (idx < 0)
+		return NULL;
+	return cfshm->tx_bufs[idx];
+}
+
+inline struct shmbuffer *tx_bump_buf(struct cfshm *cfshm,
+			struct shmbuffer *pbuf)
+{
+	u32 desc_size;
+	struct shmbuffer *newpbuf = pbuf;
+
+	WARN_ON(!spin_is_locked(&cfshm->lock));
+	if (pbuf) {
+		cfshm->xshm->cfg.tx.buf_size[pbuf->index] =
+			cpu_to_le32(pbuf->frm_ofs);
+		ringbuf_upd_writeptr(&cfshm->tx);
+		newpbuf = get_tx_buf(cfshm);
+		/* Reset buffer parameters. */
+		desc_size = (cfshm->tx_frms_pr_buf + 1) *
+			sizeof(struct shm_pck_desc);
+		pbuf->frm_ofs = desc_size + (desc_size % cfshm->rx_alignment);
+		pbuf->frames = 0;
+
+	}
+	return newpbuf;
+}
+
+static struct shmbuffer *shm_rx_func(struct cfshm *cfshm, int quota)
+{
+	struct shmbuffer *pbuf;
+	struct sk_buff *skb;
+	int ret;
+	unsigned long flags;
+
+	pbuf = get_rx_buf(cfshm);
+	while (pbuf) {
+		/* Retrieve pointer to start of the packet descriptor area. */
+		struct shm_pck_desc *pck_desc =
+			((struct shm_pck_desc *) pbuf->addr) + pbuf->frames;
+		u32 offset;
+
+		/* Loop until descriptor contains zero offset */
+		while ((offset = pck_desc->offset)) {
+			unsigned int caif_len;
+			struct shm_caif_frm *frm;
+			u32 length = pck_desc->length;
+			u8 hdr_ofs;
+			frm = (struct shm_caif_frm *)(pbuf->addr + offset);
+			hdr_ofs = frm->hdr_ofs;
+			caif_len =
+				length - SHM_HDR_LEN -
+				hdr_ofs;
+
+			pr_devel("copy data buf:%d frm:%d offs:%d @%x len:%d\n",
+					pbuf->index, pbuf->frames, offset,
+					(u32) (SHM_HDR_LEN + hdr_ofs + offset +
+						pbuf->addr - cfshm->rx_ringbuf),
+					length);
+
+			/* Check whether number of frames is below limit */
+			if (pbuf->frames > cfshm->rx_frms_pr_buf) {
+				pr_warn("Too many frames in buffer.\n");
+				++cfshm->ndev->stats.rx_frame_errors;
+				goto desc_err;
+			}
+
+			/* Check whether offset is below low limits */
+			if (pbuf->addr + offset
+					<= (u8 *)(pck_desc + 1)) {
+				pr_warn("Offset in desc. below buffer area.\n");
+				++cfshm->ndev->stats.rx_frame_errors;
+				goto desc_err;
+			}
+
+			/* Check whether offset above upper limit */
+			if (offset + length > pbuf->len) {
+				pr_warn("Offset outside buffer area:\n");
+				++cfshm->ndev->stats.rx_frame_errors;
+				goto desc_err;
+			}
+
+			skb = netdev_alloc_skb(cfshm->ndev,
+							caif_len + 1);
+			if (skb == NULL) {
+				pr_debug("Couldn't allocate SKB\n");
+				++cfshm->ndev->stats.rx_dropped;
+				goto out;
+			}
+
+			memcpy(skb_put(skb, caif_len),
+					SHM_HDR_LEN + hdr_ofs +
+					offset + pbuf->addr,
+					caif_len);
+
+			skb->protocol = htons(ETH_P_CAIF);
+			skb_reset_mac_header(skb);
+			skb->dev = cfshm->ndev;
+
+			/* Push received packet up the stack. */
+			ret = netif_receive_skb(skb);
+
+			if (!ret) {
+				cfshm->ndev->stats.rx_packets++;
+				cfshm->ndev->stats.rx_bytes +=
+					length;
+			} else
+				++cfshm->ndev->stats.rx_dropped;
+			/* Move to next packet descriptor. */
+			pck_desc++;
+
+			pbuf->frames++;
+			if (--quota <= 0) {
+				pr_devel("Quota exeeded (pbuf:%p)\n", pbuf);
+				goto out;
+			}
+		}
+desc_err:
+		pbuf->frames = 0;
+
+		spin_lock_irqsave(&cfshm->lock, flags);
+		ringbuf_upd_readptr(&cfshm->rx);
+		pbuf = new_rx_buf(cfshm);
+		spin_unlock_irqrestore(&cfshm->lock, flags);
+
+	}
+	cfshm->xshm->ipc_rx_release(cfshm->xshm, false);
+out:
+	return pbuf;
+}
+
+static int insert_skb_in_buf(struct cfshm *cfshm, struct sk_buff *skb,
+					struct shmbuffer *pbuf)
+{
+	struct shm_pck_desc *pck_desc;
+	unsigned int frmlen;
+	struct shm_caif_frm *frm;
+	u8 hdr_ofs;
+	struct caif_payload_info *info = (struct caif_payload_info *)&skb->cb;
+
+	WARN_ON(!spin_is_locked(&cfshm->lock));
+
+	if (unlikely(pbuf->frames >= cfshm->tx_frms_pr_buf)) {
+		pr_devel("-ENOSPC exeeded frames: %d >= %d\n",
+				pbuf->frames, cfshm->tx_frms_pr_buf);
+		return -ENOSPC;
+	}
+
+	/*
+	 * Align the address of the entire CAIF frame (incl padding),
+	 * so the modem can do efficient DMA of this frame
+	 * FIXME: Alignment is power of to, so it could use binary ops.
+	 */
+	pbuf->frm_ofs = roundup(pbuf->frm_ofs, cfshm->tx_alignment);
+
+
+	/* Make the payload (IP packet) inside the frame aligned */
+	hdr_ofs = (unsigned long) &pbuf->frm_ofs;
+	hdr_ofs = roundup(hdr_ofs + SHM_HDR_LEN + info->hdr_len,
+			cfshm->tx_alignment);
+
+	frm = (struct shm_caif_frm *)
+		(pbuf->addr + pbuf->frm_ofs);
+
+	frmlen = SHM_HDR_LEN + hdr_ofs + skb->len;
+
+	/*
+	 * Verify that packet, header and additional padding
+	 * can fit within the buffer frame area.
+	 */
+	if (pbuf->len < pbuf->frm_ofs + frmlen) {
+		pr_devel("-ENOSPC exeeded offset %d < %d\n",
+				pbuf->len, pbuf->frm_ofs + frmlen);
+		return -ENOSPC;
+	}
+
+	/* Copy in CAIF frame. */
+	frm->hdr_ofs = hdr_ofs;
+	skb_copy_bits(skb, 0, pbuf->addr +
+			pbuf->frm_ofs + SHM_HDR_LEN +
+			hdr_ofs, skb->len);
+
+	pr_devel("copy data buf:%d frm:%d offs:%d @%d len:%d\n",
+			pbuf->index, pbuf->frames,
+			pbuf->frm_ofs,
+			(u32) (pbuf->addr + pbuf->frm_ofs +
+				SHM_HDR_LEN + hdr_ofs - cfshm->tx_ringbuf),
+			skb->len);
+
+	cfshm->ndev->stats.tx_packets++;
+	cfshm->ndev->stats.tx_bytes += frmlen;
+	/* Fill in the shared memory packet descriptor area. */
+	pck_desc = (struct shm_pck_desc *) (pbuf->addr);
+	/* Forward to current frame. */
+	pck_desc += pbuf->frames;
+	pck_desc->offset = pbuf->frm_ofs;
+	pck_desc->length = frmlen;
+	/* Terminate packet descriptor area. */
+	pck_desc++;
+	pck_desc->offset = 0;
+	pck_desc->length = 0;
+	/* Update buffer parameters. */
+	pbuf->frames++;
+	pbuf->frm_ofs += frmlen;
+
+	return 0;
+}
+
+static struct shmbuffer *queue_to_ringbuf(struct cfshm *cfshm, int *new_bufs)
+{
+	struct shmbuffer *pbuf;
+	struct sk_buff *skb;
+	int err;
+
+	WARN_ON(!spin_is_locked(&cfshm->lock));
+
+	pbuf = get_tx_buf(cfshm);
+	while (pbuf != NULL) {
+		skb = skb_peek(&cfshm->sk_qhead);
+		if (skb == NULL)
+			break;
+		err = insert_skb_in_buf(cfshm, skb, pbuf);
+		if (unlikely(err == -ENOSPC)) {
+			pr_devel("No more space in buffer\n");
+			++(*new_bufs);
+			pbuf = tx_bump_buf(cfshm, pbuf);
+			continue;
+		}
+		skb = skb_dequeue(&cfshm->sk_qhead);
+		/* We're always in NET_*_SOFTIRQ */
+		dev_kfree_skb(skb);
+	}
+	return pbuf;
+}
+
+static int shm_netdev_open(struct net_device *netdev)
+{
+	struct cfshm *cfshm = netdev_priv(netdev);
+	int ret, err = 0;
+
+	cfshm->state = CFSHM_OPENING;
+	if (cfshm->xshm != NULL && cfshm->xshm->open != NULL)
+		err = cfshm->xshm->open(cfshm->xshm);
+	if (err)
+		goto error;
+
+	rtnl_unlock();  /* Release RTNL lock during connect wait */
+	ret = wait_event_interruptible_timeout(cfshm->netmgmt_wq,
+			cfshm->state != CFSHM_OPENING,
+			CONNECT_TIMEOUT);
+	rtnl_lock();
+
+	if (ret == 0) {
+		pr_debug("connect timeout\n");
+		err = -ETIMEDOUT;
+		goto error;
+	}
+
+	if (cfshm->state !=  CFSHM_OPEN) {
+		pr_debug("connect failed\n");
+		err = -ECONNREFUSED;
+		goto error;
+	}
+
+	napi_enable(&cfshm->napi);
+	return 0;
+error:
+	if (cfshm->xshm != NULL && cfshm->xshm->close != NULL)
+		cfshm->xshm->close(cfshm->xshm);
+	return err;
+}
+
+static int shm_netdev_close(struct net_device *netdev)
+{
+	struct cfshm *cfshm = netdev_priv(netdev);
+
+	napi_disable(&cfshm->napi);
+
+	if (cfshm->xshm != NULL && cfshm->xshm->close != NULL)
+		cfshm->xshm->close(cfshm->xshm);
+
+	return 0;
+}
+
+static int open_cb(void *drv)
+{
+	struct cfshm *cfshm = drv;
+
+	cfshm->state = CFSHM_OPEN;
+	netif_carrier_on(cfshm->ndev);
+	wake_up_interruptible(&cfshm->netmgmt_wq);
+	return 0;
+}
+
+static void close_cb(void *drv)
+{
+	struct cfshm *cfshm = drv;
+
+	cfshm->state = CFSHM_CLOSED;
+	netif_carrier_off(cfshm->ndev);
+	wake_up_interruptible(&cfshm->netmgmt_wq);
+}
+
+static int caif_shmdrv_rx_cb(void *drv)
+{
+	struct cfshm *cfshm = drv;
+
+	if (unlikely(*cfshm->xshm->cfg.rx.state == cpu_to_le32(XSHM_CLOSED)))
+		return -ESHUTDOWN;
+
+	napi_schedule(&cfshm->napi);
+	return 0;
+}
+
+static int send_pending_txbufs(struct cfshm *cfshm, int usedbufs)
+{
+	unsigned long flags;
+
+	/* Send the started buffer if used buffers are low enough */
+	WARN_ON(!spin_is_locked(&cfshm->lock));
+	if (likely(usedbufs < cfshm->stuff_mark)) {
+		struct shmbuffer *pbuf = get_tx_buf(cfshm);
+		if (unlikely(pbuf->frames > 0)) {
+			if (spin_trylock_irqsave(&cfshm->lock, flags)) {
+				WARN_ON(!spin_is_locked(&cfshm->lock));
+				pbuf = get_tx_buf(cfshm);
+				tx_bump_buf(cfshm, pbuf);
+				spin_unlock_irqrestore(&cfshm->lock, flags);
+				cfshm->xshm->ipc_tx(cfshm->xshm);
+				return 0;
+			} else {
+				return -EBUSY;
+			}
+		}
+	}
+	return 0;
+}
+
+static int caif_shmdrv_tx_release_cb(void *drv)
+{
+	struct cfshm *cfshm = drv;
+	int usedbufs;
+
+	usedbufs = ringbuf_used(&cfshm->tx);
+
+	/* Send flow-on if we have sent flow-off and get below low-water */
+	if (usedbufs <= cfshm->low_xoff_water && !cfshm->tx_flow_on) {
+		pr_debug("Flow on\n");
+		cfshm->tx_flow_on = true;
+		cfshm->cfdev.flowctrl(cfshm->ndev, CAIF_FLOW_ON);
+	}
+
+	/* If ringbuf is full, schedule NAPI to start sending */
+	if (skb_peek(&cfshm->sk_qhead) != NULL) {
+		pr_debug("Schedule NAPI to empty queue\n");
+		napi_schedule(&cfshm->napi);
+		return 0;
+	}
+
+	/* Send the started buffer if used buffers are low enough */
+	if (usedbufs < cfshm->stuff_mark) {
+		struct shmbuffer *pbuf = get_tx_buf(cfshm);
+		if (pbuf != NULL && pbuf->frames > 0)
+			napi_schedule(&cfshm->napi);
+	}
+	return 0;
+}
+
+static int shm_rx_poll(struct napi_struct *napi, int quota)
+{
+	struct cfshm *cfshm = container_of(napi, struct cfshm, napi);
+	int new_bufs;
+	struct shmbuffer *pbuf;
+	int usedbufs;
+	unsigned long flags;
+
+	/* Simply return if rx_poll is already called on other CPU */
+	if (atomic_read(&cfshm->dbg_smp_rxactive) > 0)
+		return quota;
+
+	WARN_ON(atomic_inc_return(&cfshm->dbg_smp_rxactive) > 1);
+
+	pbuf = shm_rx_func(cfshm, quota);
+
+	usedbufs = ringbuf_used(&cfshm->tx);
+
+	if (spin_trylock_irqsave(&cfshm->lock, flags)) {
+
+		/* Check if we're below "Stuff" limit, and send pending data */
+		send_pending_txbufs(cfshm, usedbufs);
+
+		/* Check if we have queued packets */
+		if (unlikely(skb_peek(&cfshm->sk_qhead) != NULL)) {
+			struct shmbuffer *txbuf;
+			WARN_ON(!spin_is_locked(&cfshm->lock));
+			pr_debug("Try to empty tx-queue\n");
+			new_bufs = 0;
+			txbuf = queue_to_ringbuf(cfshm, &new_bufs);
+
+			/* Bump out if we are configured with few buffers */
+			if (txbuf && cfshm->xshm->cfg.tx.buffers < 3) {
+				tx_bump_buf(cfshm, txbuf);
+
+				spin_unlock_irqrestore(&cfshm->lock, flags);
+				cfshm->xshm->ipc_tx(cfshm->xshm);
+				goto txdone;
+			}
+		}
+		spin_unlock_irqrestore(&cfshm->lock, flags);
+	}
+txdone:
+
+	if (pbuf == NULL)
+		napi_complete(&cfshm->napi);
+
+	atomic_dec(&cfshm->dbg_smp_rxactive);
+	return 0;
+}
+
+static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev)
+{
+	struct shmbuffer *pbuf = NULL;
+	int usedbufs;
+	int new_bufs = 0;
+	struct cfshm *cfshm = netdev_priv(shm_netdev);
+	unsigned long flags;
+
+	/*
+	 * If we have packets in queue, keep queueing to avoid
+	 * out-of-order delivery
+	 */
+	spin_lock_irqsave(&cfshm->lock, flags);
+
+	skb_queue_tail(&cfshm->sk_qhead, skb);
+	pbuf = queue_to_ringbuf(cfshm, &new_bufs);
+
+	usedbufs = ringbuf_used(&cfshm->tx);
+
+	if (usedbufs > cfshm->high_xoff_water && cfshm->tx_flow_on) {
+		pr_debug("Flow off\n");
+		cfshm->tx_flow_on = false;
+		spin_unlock_irqrestore(&cfshm->lock, flags);
+		cfshm->cfdev.flowctrl(cfshm->ndev, CAIF_FLOW_OFF);
+		return 0;
+	}
+
+	/* Check if we should accumulate more packets */
+	if (new_bufs == 0 && usedbufs > cfshm->stuff_mark) {
+		spin_unlock_irqrestore(&cfshm->lock, flags);
+		return 0;
+	}
+	tx_bump_buf(cfshm, pbuf);
+	spin_unlock_irqrestore(&cfshm->lock, flags);
+	cfshm->xshm->ipc_tx(cfshm->xshm);
+	return 0;
+}
+
+static const struct net_device_ops netdev_ops = {
+	.ndo_open = shm_netdev_open,
+	.ndo_stop = shm_netdev_close,
+	.ndo_start_xmit = shm_netdev_tx,
+};
+
+static void shm_netdev_setup(struct net_device *pshm_netdev)
+{
+	struct cfshm *cfshm;
+
+	cfshm = netdev_priv(pshm_netdev);
+	pshm_netdev->netdev_ops = &netdev_ops;
+	pshm_netdev->type = ARPHRD_CAIF;
+	pshm_netdev->hard_header_len = CAIF_NEEDED_HEADROOM;
+	pshm_netdev->tx_queue_len = 0;
+	pshm_netdev->destructor = free_netdev;
+
+	/* Initialize structures in a clean state. */
+	memset(cfshm, 0, sizeof(struct cfshm));
+}
+
+static void deinit_bufs(struct cfshm *cfshm)
+{
+	int j;
+
+	if (cfshm == NULL)
+		return;
+
+	for (j = 0; j < cfshm->xshm->cfg.rx.buffers; j++)
+		kfree(cfshm->rx_bufs[j]);
+	kfree(cfshm->rx_bufs);
+
+	for (j = 0; j < cfshm->xshm->cfg.tx.buffers; j++)
+		kfree(cfshm->tx_bufs[j]);
+	kfree(cfshm->tx_bufs);
+}
+
+static int cfshm_probe(struct xshm_dev *xshm)
+{
+	int err, j;
+	struct cfshm *cfshm = NULL;
+	struct net_device *netdev;
+	u32 buf_size;
+	unsigned long flags;
+
+	if (xshm == NULL)
+		return -EINVAL;
+	if (xshm->cfg.tx.addr == NULL || xshm->cfg.rx.addr == NULL) {
+		pr_debug("Shared Memory are not configured\n");
+		return -EINVAL;
+	}
+
+	if (xshm->cfg.tx.ch_size / xshm->cfg.tx.buffers <
+			xshm->cfg.tx.packets * sizeof(struct shm_pck_desc) +
+				xshm->cfg.tx.mtu) {
+		pr_warn("Bad packet TX-channel size");
+		return -EINVAL;
+	}
+
+	if (xshm->cfg.rx.ch_size / xshm->cfg.rx.buffers <
+			sizeof(struct shm_pck_desc) + xshm->cfg.rx.mtu) {
+		pr_warn("Bad packet RX-channel size");
+		return -EINVAL;
+	}
+
+	if (xshm->cfg.rx.buffers < 2 || xshm->cfg.tx.buffers < 2) {
+		pr_warn("Too few buffers in channel");
+		return -EINVAL;
+	}
+
+	err = -ENOMEM;
+	netdev = alloc_netdev(sizeof(struct cfshm), xshm->cfg.name,
+			shm_netdev_setup);
+
+	if (netdev == NULL)
+		goto error;
+
+	cfshm = netdev_priv(netdev);
+	cfshm->state = CFSHM_CLOSED;
+	init_waitqueue_head(&cfshm->netmgmt_wq);
+
+	cfshm->xshm = xshm;
+	xshm->driver_data = cfshm;
+	cfshm->ndev = netdev;
+	netdev->mtu = xshm->cfg.tx.mtu;
+	cfshm->high_xoff_water =
+		(xshm->cfg.rx.buffers * HIGH_XOFF_WATERMARK) / 100;
+	cfshm->low_xoff_water =
+		(xshm->cfg.rx.buffers * LOW_XOFF_WATERMARK) / 100;
+	cfshm->stuff_mark = (xshm->cfg.rx.buffers * STUFF_MARK) / 100;
+
+	cfshm->tx_frms_pr_buf = xshm->cfg.tx.packets;
+	cfshm->rx_frms_pr_buf = xshm->cfg.rx.packets;
+	cfshm->rx_alignment = xshm->cfg.rx.alignment;
+	cfshm->tx_alignment = xshm->cfg.tx.alignment;
+
+	if (xshm->cfg.latency)
+		cfshm->cfdev.link_select = CAIF_LINK_LOW_LATENCY;
+	else
+		cfshm->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
+
+	cfshm->tx.rip = xshm->cfg.tx.read;
+	cfshm->tx.wip = xshm->cfg.tx.write;
+	cfshm->tx.bufsize = xshm->cfg.tx.buf_size;
+	cfshm->tx.size = xshm->cfg.tx.buffers;
+
+	cfshm->rx.rip = xshm->cfg.rx.read;
+	cfshm->rx.wip = xshm->cfg.rx.write;
+	cfshm->rx.bufsize = xshm->cfg.rx.buf_size;
+	cfshm->rx.size = xshm->cfg.rx.buffers;
+	pr_devel("RX ri:%d wi:%d size:%d\n",
+		le32_to_cpu(*cfshm->rx.rip),
+			le32_to_cpu(*cfshm->rx.wip), cfshm->rx.size);
+	pr_devel("TX ri:%d wi:%d size:%d\n",
+		le32_to_cpu(*cfshm->tx.rip),
+			le32_to_cpu(*cfshm->tx.wip), cfshm->rx.size);
+	pr_devel("frms_pr_buf:%d %d\n", cfshm->rx_frms_pr_buf,
+			cfshm->tx_frms_pr_buf);
+
+	spin_lock_init(&cfshm->lock);
+	netif_carrier_off(netdev);
+	skb_queue_head_init(&cfshm->sk_qhead);
+
+	pr_devel("SHM DEVICE[%p] PROBED BY DRIVER, NEW SHM DRIVER"
+			" INSTANCE AT cfshm =0x%p\n",
+			cfshm->xshm, cfshm);
+
+	cfshm->tx_ringbuf = xshm->cfg.tx.addr;
+	cfshm->rx_ringbuf = xshm->cfg.rx.addr;
+
+	pr_devel("TX-BASE:%p RX-BASE:%p\n",
+			cfshm->tx_ringbuf,
+			cfshm->rx_ringbuf);
+
+	cfshm->tx_bufs = kzalloc(sizeof(struct shmbuffer *) *
+			xshm->cfg.tx.buffers, GFP_KERNEL);
+	if (cfshm->tx_bufs == NULL)
+		goto error;
+	buf_size = xshm->cfg.tx.ch_size / xshm->cfg.tx.buffers;
+
+	pr_devel("TX: buffers:%d buf_size:%d frms:%d mtu:%d\n",
+			xshm->cfg.tx.buffers, buf_size,
+			cfshm->tx_frms_pr_buf, netdev->mtu);
+
+	for (j = 0; j < xshm->cfg.tx.buffers; j++) {
+		u32 desc_size;
+		struct shmbuffer *tx_buf =
+				kzalloc(sizeof(struct shmbuffer), GFP_KERNEL);
+
+		if (tx_buf == NULL) {
+			pr_warn("ERROR, Could not"
+					" allocate dynamic mem. for tx_buf, "
+					" Bailing out ...\n");
+			goto error;
+		}
+
+		tx_buf->index = j;
+
+		tx_buf->addr = cfshm->tx_ringbuf + (buf_size * j);
+		tx_buf->len = buf_size;
+		tx_buf->frames = 0;
+		desc_size = (cfshm->tx_frms_pr_buf + 1) *
+				sizeof(struct shm_pck_desc);
+
+		tx_buf->frm_ofs = desc_size + (desc_size % cfshm->tx_alignment);
+
+		cfshm->tx_bufs[j] = tx_buf;
+
+		pr_devel("tx_buf[%d] addr:%p len:%d\n",
+				tx_buf->index,
+				tx_buf->addr,
+				tx_buf->len);
+	}
+
+	cfshm->rx_bufs = kzalloc(sizeof(struct shmbuffer *) *
+				xshm->cfg.rx.buffers, GFP_KERNEL);
+	if (cfshm->rx_bufs == NULL)
+		goto error;
+	buf_size = xshm->cfg.tx.ch_size / xshm->cfg.tx.buffers;
+	pr_devel("RX: buffers:%d buf_size:%d frms:%d mtu:%d\n",
+			xshm->cfg.rx.buffers, buf_size,
+			cfshm->rx_frms_pr_buf, netdev->mtu);
+
+	for (j = 0; j < xshm->cfg.rx.buffers; j++) {
+		struct shmbuffer *rx_buf =
+				kzalloc(sizeof(struct shmbuffer), GFP_KERNEL);
+
+		if (rx_buf == NULL) {
+			pr_warn("ERROR, Could not"
+					" allocate dynamic mem.for rx_buf, "
+					" Bailing out ...\n");
+			goto error;
+		}
+
+		rx_buf->index = j;
+
+		rx_buf->addr = cfshm->rx_ringbuf + (buf_size * j);
+		rx_buf->len = buf_size;
+		cfshm->rx_bufs[j] = rx_buf;
+		pr_devel("rx_buf[%d] addr:%p len:%d\n",
+				rx_buf->index,
+				rx_buf->addr,
+				rx_buf->len);
+	}
+
+	cfshm->tx_flow_on = 1;
+	cfshm->xshm->ipc_rx_cb = caif_shmdrv_rx_cb;
+	cfshm->xshm->ipc_tx_release_cb = caif_shmdrv_tx_release_cb;
+	cfshm->xshm->open_cb = open_cb;
+	cfshm->xshm->close_cb = close_cb;
+
+	spin_lock_irqsave(&cfshm->lock, flags);
+	get_tx_buf(cfshm);
+	new_rx_buf(cfshm);
+	spin_unlock_irqrestore(&cfshm->lock, flags);
+
+	netif_napi_add(netdev, &cfshm->napi, shm_rx_poll,
+			2 * cfshm->rx_frms_pr_buf);
+
+	netdev->dev.parent = &xshm->dev;
+	err = register_netdev(netdev);
+	if (err) {
+		pr_warn("ERROR[%d], SHM could not, "
+			"register with NW FRMWK Bailing out ...\n", err);
+		goto error;
+	}
+	return err;
+error:
+	deinit_bufs(cfshm);
+	free_netdev(netdev);
+	return err;
+}
+
+static void cfshm_remove(struct xshm_dev *xshm)
+{
+	struct cfshm *cfshm;
+
+	if (xshm == NULL || xshm->driver_data == NULL)
+		return;
+
+	cfshm = xshm->driver_data;
+	deinit_bufs(cfshm);
+	unregister_netdev(cfshm->ndev);
+
+	xshm->ipc_rx_cb = NULL;
+	xshm->ipc_tx_release_cb = NULL;
+	xshm->open_cb = NULL;
+	xshm->close_cb = NULL;
+	xshm->driver_data = NULL;
+}
+
+static struct xshm_driver cfshm_drv = {
+	.mode = XSHM_PACKET_MODE,
+	.probe = cfshm_probe,
+	.remove = cfshm_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static void __exit cfshm_exit_module(void)
+{
+	xshm_unregister_driver(&cfshm_drv);
+}
+
+static int __init cfshm_init_module(void)
+{
+	int err;
+
+	err = xshm_register_driver(&cfshm_drv);
+	if (err) {
+		printk(KERN_ERR "Could not register XSHM driver: %d.\n",
+			err);
+		goto err_dev_register;
+	}
+	return err;
+
+ err_dev_register:
+	return err;
+}
+
+module_init(cfshm_init_module);
+module_exit(cfshm_exit_module);
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 7cb2785..c7e1df9 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -1132,7 +1132,6 @@ static irqreturn_t
 e100rxtx_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct net_local *np = netdev_priv(dev);
 	unsigned long irqbits;
 
 	/*
diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/cisco/enic/enic.h
index fe0c29a..ee93a20 100644
--- a/drivers/net/ethernet/cisco/enic/enic.h
+++ b/drivers/net/ethernet/cisco/enic/enic.h
@@ -32,7 +32,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.1.1.28"
+#define DRV_VERSION		"2.1.1.31"
 #define DRV_COPYRIGHT		"Copyright 2008-2011 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 2fd9db4..045c468 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -57,11 +57,13 @@
 
 #define PCI_DEVICE_ID_CISCO_VIC_ENET         0x0043  /* ethernet vnic */
 #define PCI_DEVICE_ID_CISCO_VIC_ENET_DYN     0x0044  /* enet dynamic vnic */
+#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF      0x0071  /* enet SRIOV VF */
 
 /* Supported devices */
 static DEFINE_PCI_DEVICE_TABLE(enic_id_table) = {
 	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET) },
 	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_DYN) },
+	{ PCI_VDEVICE(CISCO, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
 	{ 0, }	/* end of table */
 };
 
@@ -132,6 +134,11 @@ int enic_sriov_enabled(struct enic *enic)
 	return (enic->priv_flags & ENIC_SRIOV_ENABLED) ? 1 : 0;
 }
 
+static int enic_is_sriov_vf(struct enic *enic)
+{
+	return enic->pdev->device == PCI_DEVICE_ID_CISCO_VIC_ENET_VF;
+}
+
 int enic_is_valid_vf(struct enic *enic, int vf)
 {
 #ifdef CONFIG_PCI_IOV
@@ -437,7 +444,7 @@ static void enic_mtu_check(struct enic *enic)
 
 	if (mtu && mtu != enic->port_mtu) {
 		enic->port_mtu = mtu;
-		if (enic_is_dynamic(enic)) {
+		if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
 			mtu = max_t(int, ENIC_MIN_MTU,
 				min_t(int, ENIC_MAX_MTU, mtu));
 			if (mtu != netdev->mtu)
@@ -849,7 +856,7 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
 {
 	struct enic *enic = netdev_priv(netdev);
 
-	if (enic_is_dynamic(enic)) {
+	if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) {
 		if (!is_valid_ether_addr(addr) && !is_zero_ether_addr(addr))
 			return -EADDRNOTAVAIL;
 	} else {
@@ -1608,7 +1615,7 @@ static int enic_open(struct net_device *netdev)
 	for (i = 0; i < enic->rq_count; i++)
 		vnic_rq_enable(&enic->rq[i]);
 
-	if (!enic_is_dynamic(enic))
+	if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
 		enic_dev_add_station_addr(enic);
 
 	enic_set_rx_mode(netdev);
@@ -1659,7 +1666,7 @@ static int enic_stop(struct net_device *netdev)
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
 
-	if (!enic_is_dynamic(enic))
+	if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
 		enic_dev_del_station_addr(enic);
 
 	for (i = 0; i < enic->wq_count; i++) {
@@ -1696,7 +1703,7 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu)
 	if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU)
 		return -EINVAL;
 
-	if (enic_is_dynamic(enic))
+	if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
 		return -EOPNOTSUPP;
 
 	if (running)
@@ -2263,10 +2270,10 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	int using_dac = 0;
 	unsigned int i;
 	int err;
-	int num_pps = 1;
 #ifdef CONFIG_PCI_IOV
 	int pos = 0;
 #endif
+	int num_pps;
 
 	/* Allocate net device structure and initialize.  Private
 	 * instance data is initialized to zero.
@@ -2373,17 +2380,17 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 				goto err_out_vnic_unregister;
 			}
 			enic->priv_flags |= ENIC_SRIOV_ENABLED;
-			num_pps = enic->num_vfs;
 		}
 	}
-
 #endif
+
+	num_pps = enic->num_vfs ? enic->num_vfs : 1;
 	/* Allocate structure for port profiles */
 	enic->pp = kcalloc(num_pps, sizeof(*enic->pp), GFP_KERNEL);
 	if (!enic->pp) {
 		pr_err("port profile alloc failed, aborting\n");
 		err = -ENOMEM;
-		goto err_out_disable_sriov;
+		goto err_out_disable_sriov_pp;
 	}
 
 	/* Issue device open to get device in known state
@@ -2392,7 +2399,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	err = enic_dev_open(enic);
 	if (err) {
 		dev_err(dev, "vNIC dev open failed, aborting\n");
-		goto err_out_free_pp;
+		goto err_out_disable_sriov;
 	}
 
 	/* Setup devcmd lock
@@ -2426,7 +2433,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	 * called later by an upper layer.
 	 */
 
-	if (!enic_is_dynamic(enic)) {
+	if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic)) {
 		err = vnic_dev_init(enic->vdev, 0);
 		if (err) {
 			dev_err(dev, "vNIC dev init failed, aborting\n");
@@ -2460,8 +2467,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	(void)enic_change_mtu(netdev, enic->port_mtu);
 
 #ifdef CONFIG_PCI_IOV
-	if (enic_is_dynamic(enic) && pdev->is_virtfn &&
-		is_zero_ether_addr(enic->mac_addr))
+	if (enic_is_sriov_vf(enic) && is_zero_ether_addr(enic->mac_addr))
 		random_ether_addr(enic->mac_addr);
 #endif
 
@@ -2474,7 +2480,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	enic->tx_coalesce_usecs = enic->config.intr_timer_usec;
 	enic->rx_coalesce_usecs = enic->tx_coalesce_usecs;
 
-	if (enic_is_dynamic(enic))
+	if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic))
 		netdev->netdev_ops = &enic_netdev_dynamic_ops;
 	else
 		netdev->netdev_ops = &enic_netdev_ops;
@@ -2516,17 +2522,17 @@ err_out_dev_deinit:
 	enic_dev_deinit(enic);
 err_out_dev_close:
 	vnic_dev_close(enic->vdev);
-err_out_free_pp:
-	kfree(enic->pp);
 err_out_disable_sriov:
+	kfree(enic->pp);
+err_out_disable_sriov_pp:
 #ifdef CONFIG_PCI_IOV
 	if (enic_sriov_enabled(enic)) {
 		pci_disable_sriov(pdev);
 		enic->priv_flags &= ~ENIC_SRIOV_ENABLED;
 	}
 err_out_vnic_unregister:
-	vnic_dev_unregister(enic->vdev);
 #endif
+	vnic_dev_unregister(enic->vdev);
 err_out_iounmap:
 	enic_iounmap(enic);
 err_out_release_regions:
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index fb5579a..47f85c3 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c
index a127cb2..bb336a0 100644
--- a/drivers/net/ethernet/faraday/ftmac100.c
+++ b/drivers/net/ethernet/faraday/ftmac100.c
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/mii.h>
 #include <linux/module.h>
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 669ca38..e8a4759 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -3878,11 +3878,9 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 				if (length <= copybreak &&
 				    skb_tailroom(skb) >= length) {
 					u8 *vaddr;
-					vaddr = kmap_atomic(buffer_info->page,
-					                    KM_SKB_DATA_SOFTIRQ);
+					vaddr = kmap_atomic(buffer_info->page);
 					memcpy(skb_tail_pointer(skb), vaddr, length);
-					kunmap_atomic(vaddr,
-					              KM_SKB_DATA_SOFTIRQ);
+					kunmap_atomic(vaddr);
 					/* re-use the page, so don't erase
 					 * buffer_info->page */
 					skb_put(skb, length);
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 3911401..7a1ea1d 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -1277,9 +1277,9 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
 			 */
 			dma_sync_single_for_cpu(&pdev->dev, ps_page->dma,
 						PAGE_SIZE, DMA_FROM_DEVICE);
-			vaddr = kmap_atomic(ps_page->page, KM_SKB_DATA_SOFTIRQ);
+			vaddr = kmap_atomic(ps_page->page);
 			memcpy(skb_tail_pointer(skb), vaddr, l1);
-			kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+			kunmap_atomic(vaddr);
 			dma_sync_single_for_device(&pdev->dev, ps_page->dma,
 						   PAGE_SIZE, DMA_FROM_DEVICE);
 
@@ -1470,12 +1470,10 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 				if (length <= copybreak &&
 				    skb_tailroom(skb) >= length) {
 					u8 *vaddr;
-					vaddr = kmap_atomic(buffer_info->page,
-					                   KM_SKB_DATA_SOFTIRQ);
+					vaddr = kmap_atomic(buffer_info->page);
 					memcpy(skb_tail_pointer(skb), vaddr,
 					       length);
-					kunmap_atomic(vaddr,
-					              KM_SKB_DATA_SOFTIRQ);
+					kunmap_atomic(vaddr);
 					/* re-use the page, so don't erase
 					 * buffer_info->page */
 					skb_put(skb, length);
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index c6e4621..6565c46 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # Intel 82575 PCI-Express Ethernet Linux driver
-# Copyright(c) 1999 - 2011 Intel Corporation.
+# Copyright(c) 1999 - 2012 Intel Corporation.
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index b8e20f0..08bdc33 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 08a757e..b927d79 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index f5fc572..aed2174 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_hw.h b/drivers/net/ethernet/intel/igb/e1000_hw.h
index 4519a13..f67cbd3 100644
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c b/drivers/net/ethernet/intel/igb/e1000_mac.c
index 73aac08..f57338a 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -151,7 +151,7 @@ void igb_clear_vfta_i350(struct e1000_hw *hw)
  *  Writes value at the given offset in the register array which stores
  *  the VLAN filter table.
  **/
-void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
+static void igb_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
 {
 	int i;
 
diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.h b/drivers/net/ethernet/intel/igb/e1000_mac.h
index e45996b..cbddc4e 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mac.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.c b/drivers/net/ethernet/intel/igb/e1000_mbx.c
index 469d95e..5988b89 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.c
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_mbx.h b/drivers/net/ethernet/intel/igb/e1000_mbx.h
index eddb0f8..dbcfa3d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_mbx.h
+++ b/drivers/net/ethernet/intel/igb/e1000_mbx.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.c b/drivers/net/ethernet/intel/igb/e1000_nvm.c
index 4040712..fa2c6ba 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.c
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_nvm.h b/drivers/net/ethernet/intel/igb/e1000_nvm.h
index a2a7ca9..825b022 100644
--- a/drivers/net/ethernet/intel/igb/e1000_nvm.h
+++ b/drivers/net/ethernet/intel/igb/e1000_nvm.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2011 Intel Corporation.
+  Copyright(c) 2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.c b/drivers/net/ethernet/intel/igb/e1000_phy.c
index b17d7c2..789de5b 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_phy.h b/drivers/net/ethernet/intel/igb/e1000_phy.h
index 8510797..4c32ac6 100644
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 0a860bc..ccdf36d 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 3d12e67..8e33bdd 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 7998bf4..aa399a8 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 01e5e89..e91d73c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel(R) Gigabit Ethernet Linux driver
-  Copyright(c) 2007-2011 Intel Corporation.
+  Copyright(c) 2007-2012 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -68,7 +68,7 @@ char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
 				"Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2012 Intel Corporation.";
 
 static const struct e1000_info *igb_info_tbl[] = {
 	[board_82575] = &e1000_82575_info,
@@ -4003,8 +4003,8 @@ set_itr_now:
 	}
 }
 
-void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
-		     u32 type_tucmd, u32 mss_l4len_idx)
+static void igb_tx_ctxtdesc(struct igb_ring *tx_ring, u32 vlan_macip_lens,
+			    u32 type_tucmd, u32 mss_l4len_idx)
 {
 	struct e1000_adv_tx_context_desc *context_desc;
 	u16 i = tx_ring->next_to_use;
@@ -5623,7 +5623,7 @@ static irqreturn_t igb_intr(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-void igb_ring_irq_enable(struct igb_q_vector *q_vector)
+static void igb_ring_irq_enable(struct igb_q_vector *q_vector)
 {
 	struct igb_adapter *adapter = q_vector->adapter;
 	struct e1000_hw *hw = &adapter->hw;
diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c
index 7b600a1..2dba534 100644
--- a/drivers/net/ethernet/intel/igbvf/ethtool.c
+++ b/drivers/net/ethernet/intel/igbvf/ethtool.c
@@ -468,6 +468,5 @@ static const struct ethtool_ops igbvf_ethtool_ops = {
 
 void igbvf_set_ethtool_ops(struct net_device *netdev)
 {
-	/* have to "undeclare" const on this struct to remove warnings */
-	SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
+	SET_ETHTOOL_OPS(netdev, &igbvf_ethtool_ops);
 }
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index fd3da30..a4b20c8 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1194,11 +1194,6 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 
-	igbvf_irq_disable(adapter);
-
-	if (!test_bit(__IGBVF_DOWN, &adapter->state))
-		igbvf_irq_enable(adapter);
-
 	if (hw->mac.ops.set_vfta(hw, vid, false)) {
 		dev_err(&adapter->pdev->dev,
 		        "Failed to remove vlan id %d\n", vid);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 802bfa0..775602e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -161,19 +161,19 @@
 
 /* Receive DMA Registers */
 #define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \
-                         (0x0D000 + ((_i - 64) * 0x40)))
+			 (0x0D000 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \
-                         (0x0D004 + ((_i - 64) * 0x40)))
+			 (0x0D004 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \
-                         (0x0D008 + ((_i - 64) * 0x40)))
+			 (0x0D008 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDH(_i)   (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \
-                         (0x0D010 + ((_i - 64) * 0x40)))
+			 (0x0D010 + (((_i) - 64) * 0x40)))
 #define IXGBE_RDT(_i)   (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \
-                         (0x0D018 + ((_i - 64) * 0x40)))
+			 (0x0D018 + (((_i) - 64) * 0x40)))
 #define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
-                          (0x0D028 + ((_i - 64) * 0x40)))
+			 (0x0D028 + (((_i) - 64) * 0x40)))
 #define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
-                          (0x0D02C + ((_i - 64) * 0x40)))
+			 (0x0D02C + (((_i) - 64) * 0x40)))
 #define IXGBE_RSCDBU     0x03028
 #define IXGBE_RDDCC      0x02F20
 #define IXGBE_RXMEMWRAP  0x03190
@@ -186,7 +186,7 @@
  */
 #define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
                           (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
-                          (0x0D014 + ((_i - 64) * 0x40))))
+			  (0x0D014 + (((_i) - 64) * 0x40))))
 /*
  * Rx DCA Control Register:
  * 00-15 : 0x02200 + n*4
@@ -195,7 +195,7 @@
  */
 #define IXGBE_DCA_RXCTRL(_i)    (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
                                  (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
-                                 (0x0D00C + ((_i - 64) * 0x40))))
+				 (0x0D00C + (((_i) - 64) * 0x40))))
 #define IXGBE_RDRXCTL           0x02F00
 #define IXGBE_RXPBSIZE(_i)      (0x03C00 + ((_i) * 4))
                                              /* 8 of these 0x03C00 - 0x03C1C */
@@ -344,9 +344,9 @@
 
 #define IXGBE_WUPL      0x05900
 #define IXGBE_WUPM      0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */
-#define IXGBE_FHFT(_n)     (0x09000 + (_n * 0x100)) /* Flex host filter table */
-#define IXGBE_FHFT_EXT(_n) (0x09800 + (_n * 0x100)) /* Ext Flexible Host
-                                                     * Filter Table */
+#define IXGBE_FHFT(_n)	(0x09000 + ((_n) * 0x100)) /* Flex host filter table */
+#define IXGBE_FHFT_EXT(_n)	(0x09800 + ((_n) * 0x100)) /* Ext Flexible Host
+							    * Filter Table */
 
 #define IXGBE_FLEXIBLE_FILTER_COUNT_MAX         4
 #define IXGBE_EXT_FLEXIBLE_FILTER_COUNT_MAX     2
@@ -1485,7 +1485,7 @@ enum {
 #define IXGBE_LED_BLINK_BASE     0x00000080
 #define IXGBE_LED_MODE_MASK_BASE 0x0000000F
 #define IXGBE_LED_OFFSET(_base, _i) (_base << (8 * (_i)))
-#define IXGBE_LED_MODE_SHIFT(_i) (8*(_i))
+#define IXGBE_LED_MODE_SHIFT(_i) (8 * (_i))
 #define IXGBE_LED_IVRT(_i)       IXGBE_LED_OFFSET(IXGBE_LED_IVRT_BASE, _i)
 #define IXGBE_LED_BLINK(_i)      IXGBE_LED_OFFSET(IXGBE_LED_BLINK_BASE, _i)
 #define IXGBE_LED_MODE_MASK(_i)  IXGBE_LED_OFFSET(IXGBE_LED_MODE_MASK_BASE, _i)
@@ -2068,9 +2068,9 @@ enum {
 
 /* SR-IOV specific macros */
 #define IXGBE_MBVFICR_INDEX(vf_number)   (vf_number >> 4)
-#define IXGBE_MBVFICR(_i)                (0x00710 + (_i * 4))
-#define IXGBE_VFLRE(_i)                  (((_i & 1) ? 0x001C0 : 0x00600))
-#define IXGBE_VFLREC(_i)                 (0x00700 + (_i * 4))
+#define IXGBE_MBVFICR(_i)		(0x00710 + ((_i) * 4))
+#define IXGBE_VFLRE(_i)		((((_i) & 1) ? 0x001C0 : 0x00600))
+#define IXGBE_VFLREC(_i)		(0x00700 + ((_i) * 4))
 
 enum ixgbe_fdir_pballoc_type {
 	IXGBE_FDIR_PBALLOC_NONE = 0,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index dc8e651..c857003 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -56,7 +56,8 @@ struct ixgbe_stats {
 			    offsetof(struct ixgbevf_adapter, m),         \
 			    offsetof(struct ixgbevf_adapter, b),         \
 			    offsetof(struct ixgbevf_adapter, r)
-static struct ixgbe_stats ixgbe_gstrings_stats[] = {
+
+static const struct ixgbe_stats ixgbe_gstrings_stats[] = {
 	{"rx_packets", IXGBEVF_STAT(stats.vfgprc, stats.base_vfgprc,
 				    stats.saved_reset_vfgprc)},
 	{"tx_packets", IXGBEVF_STAT(stats.vfgptc, stats.base_vfgptc,
@@ -671,7 +672,7 @@ static int ixgbevf_nway_reset(struct net_device *netdev)
 	return 0;
 }
 
-static struct ethtool_ops ixgbevf_ethtool_ops = {
+static const struct ethtool_ops ixgbevf_ethtool_ops = {
 	.get_settings           = ixgbevf_get_settings,
 	.get_drvinfo            = ixgbevf_get_drvinfo,
 	.get_regs_len           = ixgbevf_get_regs_len,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index e6c9d1a..9075c1d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -279,12 +279,12 @@ enum ixgbevf_boards {
 	board_X540_vf,
 };
 
-extern struct ixgbevf_info ixgbevf_82599_vf_info;
-extern struct ixgbevf_info ixgbevf_X540_vf_info;
-extern struct ixgbe_mbx_operations ixgbevf_mbx_ops;
+extern const struct ixgbevf_info ixgbevf_82599_vf_info;
+extern const struct ixgbevf_info ixgbevf_X540_vf_info;
+extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
 
 /* needed by ethtool.c */
-extern char ixgbevf_driver_name[];
+extern const char ixgbevf_driver_name[];
 extern const char ixgbevf_driver_version[];
 
 extern int ixgbevf_up(struct ixgbevf_adapter *adapter);
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 891162d..bed411b 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -53,7 +53,7 @@
 
 #include "ixgbevf.h"
 
-char ixgbevf_driver_name[] = "ixgbevf";
+const char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
 	"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
@@ -917,31 +917,34 @@ static irqreturn_t ixgbevf_msix_mbx(int irq, void *data)
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 eicr;
 	u32 msg;
+	bool got_ack = false;
 
 	eicr = IXGBE_READ_REG(hw, IXGBE_VTEICS);
 	IXGBE_WRITE_REG(hw, IXGBE_VTEICR, eicr);
 
-	if (!hw->mbx.ops.check_for_ack(hw)) {
-		/*
-		 * checking for the ack clears the PFACK bit.  Place
-		 * it back in the v2p_mailbox cache so that anyone
-		 * polling for an ack will not miss it.  Also
-		 * avoid the read below because the code to read
-		 * the mailbox will also clear the ack bit.  This was
-		 * causing lost acks.  Just cache the bit and exit
-		 * the IRQ handler.
-		 */
-		hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
-		goto out;
-	}
+	if (!hw->mbx.ops.check_for_ack(hw))
+		got_ack = true;
 
-	/* Not an ack interrupt, go ahead and read the message */
-	hw->mbx.ops.read(hw, &msg, 1);
+	if (!hw->mbx.ops.check_for_msg(hw)) {
+		hw->mbx.ops.read(hw, &msg, 1);
 
-	if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
-		mod_timer(&adapter->watchdog_timer,
-			  round_jiffies(jiffies + 1));
+		if ((msg & IXGBE_MBVFICR_VFREQ_MASK) == IXGBE_PF_CONTROL_MSG)
+			mod_timer(&adapter->watchdog_timer,
+				  round_jiffies(jiffies + 1));
 
+		if (msg & IXGBE_VT_MSGTYPE_NACK)
+			pr_warn("Last Request of type %2.2x to PF Nacked\n",
+				msg & 0xFF);
+		goto out;
+	}
+
+	/*
+	 * checking for the ack clears the PFACK bit.  Place
+	 * it back in the v2p_mailbox cache so that anyone
+	 * polling for an ack will not miss it
+	 */
+	if (got_ack)
+		hw->mbx.v2p_mailbox |= IXGBE_VFMAILBOX_PFACK;
 out:
 	return IRQ_HANDLED;
 }
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index 930fa83..13532d9 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -26,6 +26,7 @@
 *******************************************************************************/
 
 #include "mbx.h"
+#include "ixgbevf.h"
 
 /**
  *  ixgbevf_poll_for_msg - Wait for message notification
@@ -328,7 +329,7 @@ static s32 ixgbevf_init_mbx_params_vf(struct ixgbe_hw *hw)
 	return 0;
 }
 
-struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
+const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
 	.init_params   = ixgbevf_init_mbx_params_vf,
 	.read          = ixgbevf_read_mbx_vf,
 	.write         = ixgbevf_write_mbx_vf,
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 21533e3..d0138d7 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -26,6 +26,7 @@
 *******************************************************************************/
 
 #include "vf.h"
+#include "ixgbevf.h"
 
 /**
  *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
@@ -401,7 +402,7 @@ static s32 ixgbevf_check_mac_link_vf(struct ixgbe_hw *hw,
 	return 0;
 }
 
-static struct ixgbe_mac_operations ixgbevf_mac_ops = {
+static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
 	.init_hw             = ixgbevf_init_hw_vf,
 	.reset_hw            = ixgbevf_reset_hw_vf,
 	.start_hw            = ixgbevf_start_hw_vf,
@@ -415,12 +416,12 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = {
 	.set_vfta            = ixgbevf_set_vfta_vf,
 };
 
-struct ixgbevf_info ixgbevf_82599_vf_info = {
+const struct ixgbevf_info ixgbevf_82599_vf_info = {
 	.mac = ixgbe_mac_82599_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
 
-struct ixgbevf_info ixgbevf_X540_vf_info = {
+const struct ixgbevf_info ixgbevf_X540_vf_info = {
 	.mac = ixgbe_mac_X540_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index 10306b4..d556619 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -167,7 +167,7 @@ struct ixgbevf_hw_stats {
 
 struct ixgbevf_info {
 	enum ixgbe_mac_type		mac;
-	struct ixgbe_mac_operations	*mac_ops;
+	const struct ixgbe_mac_operations *mac_ops;
 };
 
 #endif /* __IXGBE_VF_H__ */
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 85e2c6c..66ec54a 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -71,10 +71,43 @@
 #define ETOP_MII_REVERSE	0xe
 #define ETOP_PLEN_UNDER		0x40
 #define ETOP_CGEN		0x800
-
-/* use 2 static channels for TX/RX */
+#define ETOP_CFG_MII0		0x01
+
+#define LTQ_GBIT_MDIO_CTL	0xCC
+#define LTQ_GBIT_MDIO_DATA	0xd0
+#define LTQ_GBIT_GCTL0		0x68
+#define LTQ_GBIT_PMAC_HD_CTL	0x8c
+#define LTQ_GBIT_P0_CTL		0x4
+#define LTQ_GBIT_PMAC_RX_IPG	0xa8
+
+#define PMAC_HD_CTL_AS		(1 << 19)
+#define PMAC_HD_CTL_RXSH	(1 << 22)
+
+/* Switch Enable (0=disable, 1=enable) */
+#define GCTL0_SE		0x80000000
+/* Disable MDIO auto polling (0=disable, 1=enable) */
+#define PX_CTL_DMDIO		0x00400000
+
+/* register information for the gbit's MDIO bus */
+#define MDIO_XR9_REQUEST	0x00008000
+#define MDIO_XR9_READ		0x00000800
+#define MDIO_XR9_WRITE		0x00000400
+#define MDIO_XR9_REG_MASK	0x1f
+#define MDIO_XR9_ADDR_MASK	0x1f
+#define MDIO_XR9_RD_MASK	0xffff
+#define MDIO_XR9_REG_OFFSET	0
+#define MDIO_XR9_ADDR_OFFSET	5
+#define MDIO_XR9_WR_OFFSET	16
+
+/* the newer xway socks have a embedded 3/7 port gbit multiplexer */
+#define ltq_has_gbit()		(ltq_is_ar9() || ltq_is_vr9())
+
+/* use 2 static channels for TX/RX
+   depending on the SoC we need to use different DMA channels for ethernet */
 #define LTQ_ETOP_TX_CHANNEL	1
-#define LTQ_ETOP_RX_CHANNEL	6
+#define LTQ_ETOP_RX_CHANNEL	((ltq_is_ase()) ? (5) : \
+				((ltq_has_gbit()) ? (0) : (6)))
+
 #define IS_TX(x)		(x == LTQ_ETOP_TX_CHANNEL)
 #define IS_RX(x)		(x == LTQ_ETOP_RX_CHANNEL)
 
@@ -83,9 +116,15 @@
 #define ltq_etop_w32_mask(x, y, z)	\
 		ltq_w32_mask(x, y, ltq_etop_membase + (z))
 
+#define ltq_gbit_r32(x)		ltq_r32(ltq_gbit_membase + (x))
+#define ltq_gbit_w32(x, y)	ltq_w32(x, ltq_gbit_membase + (y))
+#define ltq_gbit_w32_mask(x, y, z)	\
+		ltq_w32_mask(x, y, ltq_gbit_membase + (z))
+
 #define DRV_VERSION	"1.0"
 
 static void __iomem *ltq_etop_membase;
+static void __iomem *ltq_gbit_membase;
 
 struct ltq_etop_chan {
 	int idx;
@@ -111,6 +150,9 @@ struct ltq_etop_priv {
 	spinlock_t lock;
 };
 
+static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
+				int phy_reg, u16 phy_data);
+
 static int
 ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
 {
@@ -212,7 +254,7 @@ static irqreturn_t
 ltq_etop_dma_irq(int irq, void *_priv)
 {
 	struct ltq_etop_priv *priv = _priv;
-	int ch = irq - LTQ_DMA_CH0_INT;
+	int ch = irq - LTQ_DMA_ETOP;
 
 	napi_schedule(&priv->ch[ch].napi);
 	return IRQ_HANDLED;
@@ -245,15 +287,44 @@ ltq_etop_hw_exit(struct net_device *dev)
 			ltq_etop_free_channel(dev, &priv->ch[i]);
 }
 
+static void
+ltq_etop_gbit_init(void)
+{
+	ltq_pmu_enable(PMU_SWITCH);
+
+	ltq_gpio_request(42, 2, 1, "MDIO");
+	ltq_gpio_request(43, 2, 1, "MDC");
+
+	ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+	/** Disable MDIO auto polling mode */
+	ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
+	/* set 1522 packet size */
+	ltq_gbit_w32_mask(0x300, 0, LTQ_GBIT_GCTL0);
+	/* disable pmac & dmac headers */
+	ltq_gbit_w32_mask(PMAC_HD_CTL_AS | PMAC_HD_CTL_RXSH, 0,
+		LTQ_GBIT_PMAC_HD_CTL);
+	/* Due to traffic halt when burst length 8,
+		replace default IPG value with 0x3B */
+	ltq_gbit_w32(0x3B, LTQ_GBIT_PMAC_RX_IPG);
+}
+
 static int
 ltq_etop_hw_init(struct net_device *dev)
 {
 	struct ltq_etop_priv *priv = netdev_priv(dev);
+	unsigned int mii_mode = priv->pldata->mii_mode;
+	int err = 0;
 	int i;
 
 	ltq_pmu_enable(PMU_PPE);
 
-	switch (priv->pldata->mii_mode) {
+	if (ltq_has_gbit()) {
+		ltq_etop_gbit_init();
+		/* force the etops link to the gbit to MII */
+		mii_mode = PHY_INTERFACE_MODE_MII;
+	}
+
+	switch (mii_mode) {
 	case PHY_INTERFACE_MODE_RMII:
 		ltq_etop_w32_mask(ETOP_MII_MASK,
 			ETOP_MII_REVERSE, LTQ_ETOP_CFG);
@@ -265,6 +336,18 @@ ltq_etop_hw_init(struct net_device *dev)
 		break;
 
 	default:
+		if (ltq_is_ase()) {
+			ltq_pmu_enable(PMU_EPHY);
+			/* disable external MII */
+			ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
+			/* enable clock for internal PHY */
+			ltq_cgu_enable(CGU_EPHY);
+			/* we need to write this magic to the internal phy to
+			   make it work */
+			ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
+			pr_info("Selected EPHY mode\n");
+			break;
+		}
 		netdev_err(dev, "unknown mii mode %d\n",
 			priv->pldata->mii_mode);
 		return -ENOTSUPP;
@@ -275,29 +358,33 @@ ltq_etop_hw_init(struct net_device *dev)
 
 	ltq_dma_init_port(DMA_PORT_ETOP);
 
-	for (i = 0; i < MAX_DMA_CHAN; i++) {
-		int irq = LTQ_DMA_CH0_INT + i;
+	for (i = 0; i < MAX_DMA_CHAN && !err; i++) {
+		int irq = LTQ_DMA_ETOP + i;
 		struct ltq_etop_chan *ch = &priv->ch[i];
 
 		ch->idx = ch->dma.nr = i;
 
 		if (IS_TX(i)) {
 			ltq_dma_alloc_tx(&ch->dma);
-			request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+			err = request_irq(irq, ltq_etop_dma_irq, 0,
 				"etop_tx", priv);
 		} else if (IS_RX(i)) {
 			ltq_dma_alloc_rx(&ch->dma);
 			for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
 					ch->dma.desc++)
-				if (ltq_etop_alloc_skb(ch))
-					return -ENOMEM;
+				if (ltq_etop_alloc_skb(ch)) {
+					err = -ENOMEM;
+					goto err_out;
+				}
 			ch->dma.desc = 0;
-			request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+			err = request_irq(irq, ltq_etop_dma_irq, 0,
 				"etop_rx", priv);
 		}
-		ch->dma.irq = irq;
+		if (!err)
+			ch->dma.irq = irq;
 	}
-	return 0;
+err_out:
+	return err;
 }
 
 static void
@@ -340,6 +427,39 @@ static const struct ethtool_ops ltq_etop_ethtool_ops = {
 };
 
 static int
+ltq_etop_mdio_wr_xr9(struct mii_bus *bus, int phy_addr,
+		int phy_reg, u16 phy_data)
+{
+	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_WRITE |
+		(phy_data << MDIO_XR9_WR_OFFSET) |
+		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+		;
+	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+		;
+	return 0;
+}
+
+static int
+ltq_etop_mdio_rd_xr9(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+	u32 val = MDIO_XR9_REQUEST | MDIO_XR9_READ |
+		((phy_addr & MDIO_XR9_ADDR_MASK) << MDIO_XR9_ADDR_OFFSET) |
+		((phy_reg & MDIO_XR9_REG_MASK) << MDIO_XR9_REG_OFFSET);
+
+	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+		;
+	ltq_gbit_w32(val, LTQ_GBIT_MDIO_CTL);
+	while (ltq_gbit_r32(LTQ_GBIT_MDIO_CTL) & MDIO_XR9_REQUEST)
+		;
+	val = ltq_gbit_r32(LTQ_GBIT_MDIO_DATA) & MDIO_XR9_RD_MASK;
+	return val;
+}
+
+static int
 ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
 {
 	u32 val = MDIO_REQUEST |
@@ -380,14 +500,11 @@ ltq_etop_mdio_probe(struct net_device *dev)
 {
 	struct ltq_etop_priv *priv = netdev_priv(dev);
 	struct phy_device *phydev = NULL;
-	int phy_addr;
 
-	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
-		if (priv->mii_bus->phy_map[phy_addr]) {
-			phydev = priv->mii_bus->phy_map[phy_addr];
-			break;
-		}
-	}
+	if (ltq_is_ase())
+		phydev = priv->mii_bus->phy_map[8];
+	else
+		phydev = priv->mii_bus->phy_map[0];
 
 	if (!phydev) {
 		netdev_err(dev, "no PHY found\n");
@@ -409,6 +526,9 @@ ltq_etop_mdio_probe(struct net_device *dev)
 			      | SUPPORTED_Autoneg
 			      | SUPPORTED_MII
 			      | SUPPORTED_TP);
+	if (ltq_has_gbit())
+		phydev->supported &= SUPPORTED_1000baseT_Half
+					| SUPPORTED_1000baseT_Full;
 
 	phydev->advertising = phydev->supported;
 	priv->phydev = phydev;
@@ -434,8 +554,13 @@ ltq_etop_mdio_init(struct net_device *dev)
 	}
 
 	priv->mii_bus->priv = dev;
-	priv->mii_bus->read = ltq_etop_mdio_rd;
-	priv->mii_bus->write = ltq_etop_mdio_wr;
+	if (ltq_has_gbit()) {
+		priv->mii_bus->read = ltq_etop_mdio_rd_xr9;
+		priv->mii_bus->write = ltq_etop_mdio_wr_xr9;
+	} else {
+		priv->mii_bus->read = ltq_etop_mdio_rd;
+		priv->mii_bus->write = ltq_etop_mdio_wr;
+	}
 	priv->mii_bus->name = "ltq_mii";
 	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
 		priv->pdev->name, priv->pdev->id);
@@ -494,7 +619,8 @@ ltq_etop_open(struct net_device *dev)
 		ltq_dma_open(&ch->dma);
 		napi_enable(&ch->napi);
 	}
-	phy_start(priv->phydev);
+	if (priv->phydev)
+		phy_start(priv->phydev);
 	netif_tx_start_all_queues(dev);
 	return 0;
 }
@@ -506,7 +632,8 @@ ltq_etop_stop(struct net_device *dev)
 	int i;
 
 	netif_tx_stop_all_queues(dev);
-	phy_stop(priv->phydev);
+	if (priv->phydev)
+		phy_stop(priv->phydev);
 	for (i = 0; i < MAX_DMA_CHAN; i++) {
 		struct ltq_etop_chan *ch = &priv->ch[i];
 
@@ -526,9 +653,9 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
 	struct ltq_etop_priv *priv = netdev_priv(dev);
 	struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
 	struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
-	int len;
 	unsigned long flags;
 	u32 byte_offset;
+	int len;
 
 	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
 
@@ -652,9 +779,10 @@ ltq_etop_init(struct net_device *dev)
 	if (err)
 		goto err_netdev;
 	ltq_etop_set_multicast_list(dev);
-	err = ltq_etop_mdio_init(dev);
-	if (err)
-		goto err_netdev;
+	if (!ltq_etop_mdio_init(dev))
+		dev->ethtool_ops = &ltq_etop_ethtool_ops;
+	else
+		pr_warn("etop: mdio probe failed\n");
 	return 0;
 
 err_netdev:
@@ -702,7 +830,7 @@ ltq_etop_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
 	struct ltq_etop_priv *priv;
-	struct resource *res;
+	struct resource *res, *gbit_res;
 	int err;
 	int i;
 
@@ -730,10 +858,26 @@ ltq_etop_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
+	if (ltq_has_gbit()) {
+		gbit_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!gbit_res) {
+			dev_err(&pdev->dev, "failed to get gbit resource\n");
+			err = -ENOENT;
+			goto err_out;
+		}
+		ltq_gbit_membase = devm_ioremap_nocache(&pdev->dev,
+			gbit_res->start, resource_size(gbit_res));
+		if (!ltq_gbit_membase) {
+			dev_err(&pdev->dev, "failed to remap gigabit switch %d\n",
+				pdev->id);
+			err = -ENOMEM;
+			goto err_out;
+		}
+	}
+
 	dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
 	strcpy(dev->name, "eth%d");
 	dev->netdev_ops = &ltq_eth_netdev_ops;
-	dev->ethtool_ops = &ltq_etop_ethtool_ops;
 	priv = netdev_priv(dev);
 	priv->res = res;
 	priv->pdev = pdev;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index 7dbc6a2..53c6686 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -479,6 +479,95 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
 	param->tx_pending = priv->tx_ring[0].size;
 }
 
+static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	return priv->rx_ring_num;
+}
+
+static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+	int rss_rings;
+	size_t n = priv->rx_ring_num;
+	int err = 0;
+
+	rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+
+	while (n--) {
+		ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+			rss_map->base_qpn;
+	}
+
+	return err;
+}
+
+static int mlx4_en_set_rxfh_indir(struct net_device *dev,
+		const u32 *ring_index)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	int port_up = 0;
+	int err = 0;
+	int i;
+	int rss_rings = 0;
+
+	/* Calculate RSS table size and make sure flows are spread evenly
+	 * between rings
+	 */
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		if (i > 0 && !ring_index[i] && !rss_rings)
+			rss_rings = i;
+
+		if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+			return -EINVAL;
+	}
+
+	if (!rss_rings)
+		rss_rings = priv->rx_ring_num;
+
+	/* RSS table size must be an order of 2 */
+	if (!is_power_of_2(rss_rings))
+		return -EINVAL;
+
+	mutex_lock(&mdev->state_lock);
+	if (priv->port_up) {
+		port_up = 1;
+		mlx4_en_stop_port(dev);
+	}
+
+	priv->prof->rss_rings = rss_rings;
+
+	if (port_up) {
+		err = mlx4_en_start_port(dev);
+		if (err)
+			en_err(priv, "Failed starting port\n");
+	}
+
+	mutex_unlock(&mdev->state_lock);
+	return err;
+}
+
+static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+			     u32 *rule_locs)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	int err = 0;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_GRXRINGS:
+		cmd->data = priv->rx_ring_num;
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
 const struct ethtool_ops mlx4_en_ethtool_ops = {
 	.get_drvinfo = mlx4_en_get_drvinfo,
 	.get_settings = mlx4_en_get_settings,
@@ -498,6 +587,10 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
 	.set_pauseparam = mlx4_en_set_pauseparam,
 	.get_ringparam = mlx4_en_get_ringparam,
 	.set_ringparam = mlx4_en_set_ringparam,
+	.get_rxnfc = mlx4_en_get_rxnfc,
+	.get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+	.get_rxfh_indir = mlx4_en_get_rxfh_indir,
+	.set_rxfh_indir = mlx4_en_set_rxfh_indir,
 };
 
 
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index a06096f..2097a7d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -62,10 +62,6 @@ static const char mlx4_en_version[] =
  * Device scope module parameters
  */
 
-
-/* Enable RSS TCP traffic */
-MLX4_EN_PARM_INT(tcp_rss, 1,
-		 "Enable RSS for incomming TCP traffic or disabled (0)");
 /* Enable RSS UDP traffic */
 MLX4_EN_PARM_INT(udp_rss, 1,
 		 "Enable RSS for incomming UDP traffic or disabled (0)");
@@ -104,7 +100,6 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
 	struct mlx4_en_profile *params = &mdev->profile;
 	int i;
 
-	params->tcp_rss = tcp_rss;
 	params->udp_rss = udp_rss;
 	if (params->udp_rss && !(mdev->dev->caps.flags
 					& MLX4_DEV_CAP_FLAG_UDP_RSS)) {
@@ -120,6 +115,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
 		params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
 		params->prof[i].tx_ring_num = MLX4_EN_NUM_TX_RINGS +
 			(!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+		params->prof[i].rss_rings = 0;
 	}
 
 	return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index e8d6ad2..971d4b6 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -853,6 +853,7 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
 	struct mlx4_en_rss_map *rss_map = &priv->rss_map;
 	struct mlx4_qp_context context;
 	struct mlx4_rss_context *rss_context;
+	int rss_rings;
 	void *ptr;
 	u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
 			MLX4_RSS_TCP_IPV6);
@@ -893,10 +894,15 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
 	mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
 				priv->rx_ring[0].cqn, &context);
 
+	if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+		rss_rings = priv->rx_ring_num;
+	else
+		rss_rings = priv->prof->rss_rings;
+
 	ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
 					+ MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
 	rss_context = ptr;
-	rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+	rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
 					    (rss_map->base_qpn));
 	rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
 	if (priv->mdev->profile.udp_rss) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index f2a8e65..f4d189a 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -325,11 +325,11 @@ struct mlx4_en_port_profile {
 	u8 rx_ppp;
 	u8 tx_pause;
 	u8 tx_ppp;
+	int rss_rings;
 };
 
 struct mlx4_en_profile {
 	int rss_xor;
-	int tcp_rss;
 	int udp_rss;
 	u8 rss_mask;
 	u32 active_ports;
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 964e9c0..3ead111 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
@@ -1745,6 +1745,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 	struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
 	int err;
 
+	/* Ensure we have a valid MAC */
+	if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+		pr_err("Error: Invalid MAC address\n");
+		return -EINVAL;
+	}
+
 	/* hardware has been reset, we need to reload some things */
 	pch_gbe_set_multi(netdev);
 
@@ -2468,9 +2474,14 @@ static int pch_gbe_probe(struct pci_dev *pdev,
 
 	memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
 	if (!is_valid_ether_addr(netdev->dev_addr)) {
-		dev_err(&pdev->dev, "Invalid MAC Address\n");
-		ret = -EIO;
-		goto err_free_adapter;
+		/*
+		 * If the MAC is invalid (or just missing), display a warning
+		 * but do not abort setting up the device. pch_gbe_up will
+		 * prevent the interface from being brought up until a valid MAC
+		 * is set.
+		 */
+		dev_err(&pdev->dev, "Invalid MAC address, "
+		                    "interface disabled.\n");
 	}
 	setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
 		    (unsigned long)adapter);
diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c
index f10665f..f459c3a 100644
--- a/drivers/net/ethernet/sun/cassini.c
+++ b/drivers/net/ethernet/sun/cassini.c
@@ -104,8 +104,8 @@
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
-#define cas_page_map(x)      kmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
-#define cas_page_unmap(x)    kunmap_atomic((x), KM_SKB_DATA_SOFTIRQ)
+#define cas_page_map(x)      kmap_atomic((x))
+#define cas_page_unmap(x)    kunmap_atomic((x))
 #define CAS_NCPUS            num_online_cpus()
 
 #define cas_skb_release(x)  netif_rx(x)
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index b97a40e..3876c7e 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -31,6 +31,12 @@ config B43_BCMA
 	depends on B43 && BCMA
 	default y
 
+config B43_BCMA_EXTRA
+	bool "Hardware support that overlaps with the brcmsmac driver"
+	depends on B43_BCMA
+	default n if BRCMSMAC || BRCMSMAC_MODULE
+	default	y
+
 config B43_SSB
 	bool
 	depends on B43 && SSB
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index b91f28e..23ffb1b 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -116,8 +116,10 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
 #ifdef CONFIG_B43_BCMA
 static const struct bcma_device_id b43_bcma_tbl[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+#ifdef CONFIG_B43_BCMA_EXTRA
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
+#endif
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
 	BCMA_CORETABLE_END
 };
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index f7ed340..f6affc6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7981,13 +7981,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
 
 void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
 {
+	int timeout = 20;
+
 	/* flush packet queue when requested */
 	if (drop)
 		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
 
 	/* wait for queue and DMA fifos to run dry */
-	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
 		brcms_msleep(wlc->wl, 1);
+
+		if (--timeout == 0)
+			break;
+	}
+
+	WARN_ON_ONCE(timeout == 0);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index 760c6d7..833c0ec 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -50,7 +50,7 @@
  */
 #undef START_IN_KERNEL_MODE
 
-#define DRV_VER "0.5.24"
+#define DRV_VER "0.5.26"
 
 /*
  * According to the Atom N270 datasheet,
@@ -83,8 +83,8 @@ static int kernelmode;
 #endif
 
 static unsigned int interval = 10;
-static unsigned int fanon = 63000;
-static unsigned int fanoff = 58000;
+static unsigned int fanon = 60000;
+static unsigned int fanoff = 53000;
 static unsigned int verbose;
 static unsigned int fanstate = ACERHDF_FAN_AUTO;
 static char force_bios[16];
@@ -150,6 +150,8 @@ static const struct bios_settings_t bios_tbl[] = {
 	{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
 	{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
 	{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+	/* LT1005u */
+	{"Acer", "LT-10Q", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
 	/* Acer 1410 */
 	{"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
@@ -161,6 +163,7 @@ static const struct bios_settings_t bios_tbl[] = {
 	{"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+	{"Acer", "Aspire 1410", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
 	/* Acer 1810xx */
 	{"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1810T",  "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
@@ -183,29 +186,44 @@ static const struct bios_settings_t bios_tbl[] = {
 	{"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1810T",  "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
 	{"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
+	{"Acer", "Aspire 1810T",  "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
 	/* Acer 531 */
+	{"Acer", "AO531h", "v0.3104", 0x55, 0x58, {0x20, 0x00} },
 	{"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
+	{"Acer", "AO531h", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
+	/* Acer 751 */
+	{"Acer", "AO751h", "V0.3212", 0x55, 0x58, {0x21, 0x00} },
+	/* Acer 1825 */
+	{"Acer", "Aspire 1825PTZ", "V1.3118", 0x55, 0x58, {0x9e, 0x00} },
+	{"Acer", "Aspire 1825PTZ", "V1.3127", 0x55, 0x58, {0x9e, 0x00} },
+	/* Acer TravelMate 7730 */
+	{"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00} },
 	/* Gateway */
-	{"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
-	{"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
-	{"Gateway", "LT31",   "v1.3103", 0x55, 0x58, {0x9e, 0x00} },
-	{"Gateway", "LT31",   "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
-	{"Gateway", "LT31",   "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+	{"Gateway", "AOA110", "v0.3103",  0x55, 0x58, {0x21, 0x00} },
+	{"Gateway", "AOA150", "v0.3103",  0x55, 0x58, {0x20, 0x00} },
+	{"Gateway", "LT31",   "v1.3103",  0x55, 0x58, {0x9e, 0x00} },
+	{"Gateway", "LT31",   "v1.3201",  0x55, 0x58, {0x9e, 0x00} },
+	{"Gateway", "LT31",   "v1.3302",  0x55, 0x58, {0x9e, 0x00} },
+	{"Gateway", "LT31",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
 	/* Packard Bell */
-	{"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
-	{"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
-	{"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
-	{"Packard Bell", "DOTMU",  "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMU",  "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMA",  "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
-	{"Packard Bell", "DOTMA",  "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOA150",  "v0.3104",  0x55, 0x58, {0x21, 0x00} },
+	{"Packard Bell", "DOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00} },
+	{"Packard Bell", "AOA110",  "v0.3105",  0x55, 0x58, {0x21, 0x00} },
+	{"Packard Bell", "AOA150",  "v0.3105",  0x55, 0x58, {0x20, 0x00} },
+	{"Packard Bell", "ENBFT",   "V1.3118",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "ENBFT",   "V1.3127",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v1.3303",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3120",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3108",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3113",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3115",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3117",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v0.3119",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMU",   "v1.3204",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMA",   "v1.3201",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMA",   "v1.3302",  0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTMA",   "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
+	{"Packard Bell", "DOTVR46", "v1.3308",  0x55, 0x58, {0x9e, 0x00} },
 	/* pewpew-terminator */
 	{"", "", "", 0, 0, {0, 0} }
 };
@@ -704,15 +722,20 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Peter Feuerer");
 MODULE_DESCRIPTION("Aspire One temperature and fan driver");
 MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1825PTZ:");
 MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
+MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:");
 MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:");
 
 module_init(acerhdf_init);
 module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index c006dee..f5d369d 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -347,6 +347,7 @@ static void sony_laptop_report_input_event(u8 event)
 	struct input_dev *jog_dev = sony_laptop_input.jog_dev;
 	struct input_dev *key_dev = sony_laptop_input.key_dev;
 	struct sony_laptop_keypress kp = { NULL };
+	int scancode = -1;
 
 	if (event == SONYPI_EVENT_FNKEY_RELEASED ||
 			event == SONYPI_EVENT_ANYBUTTON_RELEASED) {
@@ -380,8 +381,9 @@ static void sony_laptop_report_input_event(u8 event)
 			dprintk("sony_laptop_report_input_event, event not known: %d\n", event);
 			break;
 		}
-		if (sony_laptop_input_index[event] != -1) {
-			kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]];
+		scancode = sony_laptop_input_index[event];
+		if (scancode != -1) {
+			kp.key = sony_laptop_input_keycode_map[scancode];
 			if (kp.key != KEY_UNKNOWN)
 				kp.dev = key_dev;
 		}
@@ -389,9 +391,13 @@ static void sony_laptop_report_input_event(u8 event)
 	}
 
 	if (kp.dev) {
+		/*
+		 * If we have a scancode we emit it so we can always remap the
+		 * key
+		 */
+		if (scancode != -1)
+			input_event(kp.dev, EV_MSC, MSC_SCAN, scancode);
 		input_report_key(kp.dev, kp.key, 1);
-		/* we emit the scancode so we can always remap the key */
-		input_event(kp.dev, EV_MSC, MSC_SCAN, event);
 		input_sync(kp.dev);
 
 		/* schedule key release */
@@ -466,7 +472,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
 	jog_dev->name = "Sony Vaio Jogdial";
 	jog_dev->id.bustype = BUS_ISA;
 	jog_dev->id.vendor = PCI_VENDOR_ID_SONY;
-	key_dev->dev.parent = &acpi_device->dev;
+	jog_dev->dev.parent = &acpi_device->dev;
 
 	input_set_capability(jog_dev, EV_KEY, BTN_MIDDLE);
 	input_set_capability(jog_dev, EV_REL, REL_WHEEL);
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
new file mode 100644
index 0000000..25fc4cc
--- /dev/null
+++ b/drivers/remoteproc/Kconfig
@@ -0,0 +1,29 @@
+menu "Remoteproc drivers (EXPERIMENTAL)"
+
+# REMOTEPROC gets selected by whoever wants it
+config REMOTEPROC
+	tristate
+	depends on EXPERIMENTAL
+
+config OMAP_REMOTEPROC
+	tristate "OMAP remoteproc support"
+	depends on ARCH_OMAP4
+	select OMAP_IOMMU
+	select REMOTEPROC
+	select OMAP_MBOX_FWK
+	select RPMSG
+	default m
+	help
+	  Say y here to support OMAP's remote processors (dual M3
+	  and DSP on OMAP4) via the remote processor framework.
+
+	  Currently only supported on OMAP4.
+
+	  Usually you want to say y here, in order to enable multimedia
+	  use-cases to run on your platform (multimedia codecs are
+	  offloaded to remote DSP processors using this framework).
+
+	  It's safe to say n here if you're not interested in multimedia
+	  offloading or just want a bare minimum kernel.
+
+endmenu
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
new file mode 100644
index 0000000..df0897f
--- /dev/null
+++ b/drivers/remoteproc/Makefile
@@ -0,0 +1,9 @@
+#
+# Generic framework for controlling remote processors
+#
+
+obj-$(CONFIG_REMOTEPROC)		+= remoteproc.o
+remoteproc-y				:= remoteproc_core.o
+remoteproc-y				+= remoteproc_debugfs.o
+remoteproc-y				+= remoteproc_rpmsg.o
+obj-$(CONFIG_OMAP_REMOTEPROC)		+= omap_remoteproc.o
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
new file mode 100644
index 0000000..aa3ce52
--- /dev/null
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -0,0 +1,238 @@
+/*
+ * OMAP Remote Processor driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ * Fernando Guzman Lugo <fernando.lugo@ti.com>
+ * Mark Grosen <mgrosen@ti.com>
+ * Suman Anna <s-anna@ti.com>
+ * Hari Kanigeri <h-kanigeri2@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/remoteproc.h>
+
+#include <plat/mailbox.h>
+#include <plat/remoteproc.h>
+
+#include "omap_remoteproc.h"
+#include "remoteproc_internal.h"
+
+/**
+ * struct omap_rproc - omap remote processor state
+ * @mbox: omap mailbox handle
+ * @nb: notifier block that will be invoked on inbound mailbox messages
+ * @rproc: rproc handle
+ */
+struct omap_rproc {
+	struct omap_mbox *mbox;
+	struct notifier_block nb;
+	struct rproc *rproc;
+};
+
+/**
+ * omap_rproc_mbox_callback() - inbound mailbox message handler
+ * @this: notifier block
+ * @index: unused
+ * @data: mailbox payload
+ *
+ * This handler is invoked by omap's mailbox driver whenever a mailbox
+ * message is received. Usually, the mailbox payload simply contains
+ * the index of the virtqueue that is kicked by the remote processor,
+ * and we let remoteproc core handle it.
+ *
+ * In addition to virtqueue indices, we also have some out-of-band values
+ * that indicates different events. Those values are deliberately very
+ * big so they don't coincide with virtqueue indices.
+ */
+static int omap_rproc_mbox_callback(struct notifier_block *this,
+					unsigned long index, void *data)
+{
+	mbox_msg_t msg = (mbox_msg_t) data;
+	struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
+	struct device *dev = oproc->rproc->dev;
+	const char *name = oproc->rproc->name;
+
+	dev_dbg(dev, "mbox msg: 0x%x\n", msg);
+
+	switch (msg) {
+	case RP_MBOX_CRASH:
+		/* just log this for now. later, we'll also do recovery */
+		dev_err(dev, "omap rproc %s crashed\n", name);
+		break;
+	case RP_MBOX_ECHO_REPLY:
+		dev_info(dev, "received echo reply from %s\n", name);
+		break;
+	default:
+		/* ignore vq indices which are too large to be valid */
+		if (msg >= 2) {
+			dev_warn(dev, "invalid mbox msg: 0x%x\n", msg);
+			break;
+		}
+
+		/*
+		 * At this point, 'msg' contains the index of the vring
+		 * which was just triggered.
+		 */
+		if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
+			dev_dbg(dev, "no message was found in vqid %d\n", msg);
+	}
+
+	return NOTIFY_DONE;
+}
+
+/* kick a virtqueue */
+static void omap_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct omap_rproc *oproc = rproc->priv;
+	int ret;
+
+	/* send the index of the triggered virtqueue in the mailbox payload */
+	ret = omap_mbox_msg_send(oproc->mbox, vqid);
+	if (ret)
+		dev_err(rproc->dev, "omap_mbox_msg_send failed: %d\n", ret);
+}
+
+/*
+ * Power up the remote processor.
+ *
+ * This function will be invoked only after the firmware for this rproc
+ * was loaded, parsed successfully, and all of its resource requirements
+ * were met.
+ */
+static int omap_rproc_start(struct rproc *rproc)
+{
+	struct omap_rproc *oproc = rproc->priv;
+	struct platform_device *pdev = to_platform_device(rproc->dev);
+	struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
+	int ret;
+
+	oproc->nb.notifier_call = omap_rproc_mbox_callback;
+
+	/* every omap rproc is assigned a mailbox instance for messaging */
+	oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
+	if (IS_ERR(oproc->mbox)) {
+		ret = PTR_ERR(oproc->mbox);
+		dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Ping the remote processor. this is only for sanity-sake;
+	 * there is no functional effect whatsoever.
+	 *
+	 * Note that the reply will _not_ arrive immediately: this message
+	 * will wait in the mailbox fifo until the remote processor is booted.
+	 */
+	ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
+	if (ret) {
+		dev_err(rproc->dev, "omap_mbox_get failed: %d\n", ret);
+		goto put_mbox;
+	}
+
+	ret = pdata->device_enable(pdev);
+	if (ret) {
+		dev_err(rproc->dev, "omap_device_enable failed: %d\n", ret);
+		goto put_mbox;
+	}
+
+	return 0;
+
+put_mbox:
+	omap_mbox_put(oproc->mbox, &oproc->nb);
+	return ret;
+}
+
+/* power off the remote processor */
+static int omap_rproc_stop(struct rproc *rproc)
+{
+	struct platform_device *pdev = to_platform_device(rproc->dev);
+	struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
+	struct omap_rproc *oproc = rproc->priv;
+	int ret;
+
+	ret = pdata->device_shutdown(pdev);
+	if (ret)
+		return ret;
+
+	omap_mbox_put(oproc->mbox, &oproc->nb);
+
+	return 0;
+}
+
+static struct rproc_ops omap_rproc_ops = {
+	.start		= omap_rproc_start,
+	.stop		= omap_rproc_stop,
+	.kick		= omap_rproc_kick,
+};
+
+static int __devinit omap_rproc_probe(struct platform_device *pdev)
+{
+	struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
+	struct omap_rproc *oproc;
+	struct rproc *rproc;
+	int ret;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(pdev->dev.parent, "dma_set_coherent_mask: %d\n", ret);
+		return ret;
+	}
+
+	rproc = rproc_alloc(&pdev->dev, pdata->name, &omap_rproc_ops,
+				pdata->firmware, sizeof(*oproc));
+	if (!rproc)
+		return -ENOMEM;
+
+	oproc = rproc->priv;
+	oproc->rproc = rproc;
+
+	platform_set_drvdata(pdev, rproc);
+
+	ret = rproc_register(rproc);
+	if (ret)
+		goto free_rproc;
+
+	return 0;
+
+free_rproc:
+	rproc_free(rproc);
+	return ret;
+}
+
+static int __devexit omap_rproc_remove(struct platform_device *pdev)
+{
+	struct rproc *rproc = platform_get_drvdata(pdev);
+
+	return rproc_unregister(rproc);
+}
+
+static struct platform_driver omap_rproc_driver = {
+	.probe = omap_rproc_probe,
+	.remove = __devexit_p(omap_rproc_remove),
+	.driver = {
+		.name = "omap-rproc",
+		.owner = THIS_MODULE,
+	},
+};
+
+module_platform_driver(omap_rproc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("OMAP Remote Processor control driver");
diff --git a/drivers/remoteproc/omap_remoteproc.h b/drivers/remoteproc/omap_remoteproc.h
new file mode 100644
index 0000000..f6d2036
--- /dev/null
+++ b/drivers/remoteproc/omap_remoteproc.h
@@ -0,0 +1,69 @@
+/*
+ * Remote processor messaging
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ * 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 Texas Instruments 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 _OMAP_RPMSG_H
+#define _OMAP_RPMSG_H
+
+/*
+ * enum - Predefined Mailbox Messages
+ *
+ * @RP_MBOX_READY: informs the M3's that we're up and running. this is
+ * part of the init sequence sent that the M3 expects to see immediately
+ * after it is booted.
+ *
+ * @RP_MBOX_PENDING_MSG: informs the receiver that there is an inbound
+ * message waiting in its own receive-side vring. please note that currently
+ * this message is optional: alternatively, one can explicitly send the index
+ * of the triggered virtqueue itself. the preferred approach will be decided
+ * as we progress and experiment with those two different approaches.
+ *
+ * @RP_MBOX_CRASH: this message is sent if BIOS crashes
+ *
+ * @RP_MBOX_ECHO_REQUEST: a mailbox-level "ping" message.
+ *
+ * @RP_MBOX_ECHO_REPLY: a mailbox-level reply to a "ping"
+ *
+ * @RP_MBOX_ABORT_REQUEST: a "please crash" request, used for testing the
+ * recovery mechanism (to some extent).
+ */
+enum omap_rp_mbox_messages {
+	RP_MBOX_READY		= 0xFFFFFF00,
+	RP_MBOX_PENDING_MSG	= 0xFFFFFF01,
+	RP_MBOX_CRASH		= 0xFFFFFF02,
+	RP_MBOX_ECHO_REQUEST	= 0xFFFFFF03,
+	RP_MBOX_ECHO_REPLY	= 0xFFFFFF04,
+	RP_MBOX_ABORT_REQUEST	= 0xFFFFFF05,
+};
+
+#endif /* _OMAP_RPMSG_H */
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
new file mode 100644
index 0000000..6212b82
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -0,0 +1,1438 @@
+/*
+ * Remote Processor Framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ * Mark Grosen <mgrosen@ti.com>
+ * Fernando Guzman Lugo <fernando.lugo@ti.com>
+ * Suman Anna <s-anna@ti.com>
+ * Robert Tivy <rtivy@ti.com>
+ * Armando Uribe De Leon <x0095078@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.
+ */
+
+#define pr_fmt(fmt)    "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/debugfs.h>
+#include <linux/remoteproc.h>
+#include <linux/iommu.h>
+#include <linux/klist.h>
+#include <linux/elf.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_ring.h>
+
+#include "remoteproc_internal.h"
+
+static void klist_rproc_get(struct klist_node *n);
+static void klist_rproc_put(struct klist_node *n);
+
+/*
+ * klist of the available remote processors.
+ *
+ * We need this in order to support name-based lookups (needed by the
+ * rproc_get_by_name()).
+ *
+ * That said, we don't use rproc_get_by_name() anymore within the rpmsg
+ * framework. The use cases that do require its existence should be
+ * scrutinized, and hopefully migrated to rproc_boot() using device-based
+ * binding.
+ *
+ * If/when this materializes, we could drop the klist (and the by_name
+ * API).
+ */
+static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put);
+
+typedef int (*rproc_handle_resources_t)(struct rproc *rproc,
+				struct fw_resource *rsc, int len);
+
+/*
+ * This is the IOMMU fault handler we register with the IOMMU API
+ * (when relevant; not all remote processors access memory through
+ * an IOMMU).
+ *
+ * IOMMU core will invoke this handler whenever the remote processor
+ * will try to access an unmapped device address.
+ *
+ * Currently this is mostly a stub, but it will be later used to trigger
+ * the recovery of the remote processor.
+ */
+static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev,
+		unsigned long iova, int flags)
+{
+	dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags);
+
+	/*
+	 * Let the iommu core know we're not really handling this fault;
+	 * we just plan to use this as a recovery trigger.
+	 */
+	return -ENOSYS;
+}
+
+static int rproc_enable_iommu(struct rproc *rproc)
+{
+	struct iommu_domain *domain;
+	struct device *dev = rproc->dev;
+	int ret;
+
+	/*
+	 * We currently use iommu_present() to decide if an IOMMU
+	 * setup is needed.
+	 *
+	 * This works for simple cases, but will easily fail with
+	 * platforms that do have an IOMMU, but not for this specific
+	 * rproc.
+	 *
+	 * This will be easily solved by introducing hw capabilities
+	 * that will be set by the remoteproc driver.
+	 */
+	if (!iommu_present(dev->bus)) {
+		dev_dbg(dev, "iommu not found\n");
+		return 0;
+	}
+
+	domain = iommu_domain_alloc(dev->bus);
+	if (!domain) {
+		dev_err(dev, "can't alloc iommu domain\n");
+		return -ENOMEM;
+	}
+
+	iommu_set_fault_handler(domain, rproc_iommu_fault);
+
+	ret = iommu_attach_device(domain, dev);
+	if (ret) {
+		dev_err(dev, "can't attach iommu device: %d\n", ret);
+		goto free_domain;
+	}
+
+	rproc->domain = domain;
+
+	return 0;
+
+free_domain:
+	iommu_domain_free(domain);
+	return ret;
+}
+
+static void rproc_disable_iommu(struct rproc *rproc)
+{
+	struct iommu_domain *domain = rproc->domain;
+	struct device *dev = rproc->dev;
+
+	if (!domain)
+		return;
+
+	iommu_detach_device(domain, dev);
+	iommu_domain_free(domain);
+
+	return;
+}
+
+/*
+ * Some remote processors will ask us to allocate them physically contiguous
+ * memory regions (which we call "carveouts"), and map them to specific
+ * device addresses (which are hardcoded in the firmware).
+ *
+ * They may then ask us to copy objects into specific device addresses (e.g.
+ * code/data sections) or expose us certain symbols in other device address
+ * (e.g. their trace buffer).
+ *
+ * This function is an internal helper with which we can go over the allocated
+ * carveouts and translate specific device address to kernel virtual addresses
+ * so we can access the referenced memory.
+ *
+ * Note: phys_to_virt(iommu_iova_to_phys(rproc->domain, da)) will work too,
+ * but only on kernel direct mapped RAM memory. Instead, we're just using
+ * here the output of the DMA API, which should be more correct.
+ */
+static void *rproc_da_to_va(struct rproc *rproc, u64 da, int len)
+{
+	struct rproc_mem_entry *carveout;
+	void *ptr = NULL;
+
+	list_for_each_entry(carveout, &rproc->carveouts, node) {
+		int offset = da - carveout->da;
+
+		/* try next carveout if da is too small */
+		if (offset < 0)
+			continue;
+
+		/* try next carveout if da is too large */
+		if (offset + len > carveout->len)
+			continue;
+
+		ptr = carveout->va + offset;
+
+		break;
+	}
+
+	return ptr;
+}
+
+/**
+ * rproc_load_segments() - load firmware segments to memory
+ * @rproc: remote processor which will be booted using these fw segments
+ * @elf_data: the content of the ELF firmware image
+ * @len: firmware size (in bytes)
+ *
+ * This function loads the firmware segments to memory, where the remote
+ * processor expects them.
+ *
+ * Some remote processors will expect their code and data to be placed
+ * in specific device addresses, and can't have them dynamically assigned.
+ *
+ * We currently support only those kind of remote processors, and expect
+ * the program header's paddr member to contain those addresses. We then go
+ * through the physically contiguous "carveout" memory regions which we
+ * allocated (and mapped) earlier on behalf of the remote processor,
+ * and "translate" device address to kernel addresses, so we can copy the
+ * segments where they are expected.
+ *
+ * Currently we only support remote processors that required carveout
+ * allocations and got them mapped onto their iommus. Some processors
+ * might be different: they might not have iommus, and would prefer to
+ * directly allocate memory for every segment/resource. This is not yet
+ * supported, though.
+ */
+static int
+rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len)
+{
+	struct device *dev = rproc->dev;
+	struct elf32_hdr *ehdr;
+	struct elf32_phdr *phdr;
+	int i, ret = 0;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+	phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff);
+
+	/* go through the available ELF segments */
+	for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
+		u32 da = phdr->p_paddr;
+		u32 memsz = phdr->p_memsz;
+		u32 filesz = phdr->p_filesz;
+		u32 offset = phdr->p_offset;
+		void *ptr;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n",
+					phdr->p_type, da, memsz, filesz);
+
+		if (filesz > memsz) {
+			dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n",
+							filesz, memsz);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (offset + filesz > len) {
+			dev_err(dev, "truncated fw: need 0x%x avail 0x%x\n",
+					offset + filesz, len);
+			ret = -EINVAL;
+			break;
+		}
+
+		/* grab the kernel address for this device address */
+		ptr = rproc_da_to_va(rproc, da, memsz);
+		if (!ptr) {
+			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
+			ret = -EINVAL;
+			break;
+		}
+
+		/* put the segment where the remote processor expects it */
+		if (phdr->p_filesz)
+			memcpy(ptr, elf_data + phdr->p_offset, filesz);
+
+		/*
+		 * Zero out remaining memory for this segment.
+		 *
+		 * This isn't strictly required since dma_alloc_coherent already
+		 * did this for us. albeit harmless, we may consider removing
+		 * this.
+		 */
+		if (memsz > filesz)
+			memset(ptr + filesz, 0, memsz - filesz);
+	}
+
+	return ret;
+}
+
+/**
+ * rproc_handle_virtio_hdr() - handle a virtio header resource
+ * @rproc: the remote processor
+ * @rsc: the resource descriptor
+ *
+ * The existence of this virtio hdr resource entry means that the firmware
+ * of this @rproc supports this virtio device.
+ *
+ * Currently we support only a single virtio device of type VIRTIO_ID_RPMSG,
+ * but the plan is to remove this limitation and support any number
+ * of virtio devices (and of any type). We'll also add support for dynamically
+ * adding (and removing) virtio devices over the rpmsg bus, but small
+ * firmwares that doesn't want to get involved with rpmsg will be able
+ * to simple use the resource table for this.
+ *
+ * At this point this virtio header entry is rather simple: it just
+ * announces the virtio device id and the supported virtio device features.
+ * The plan though is to extend this to include the vring information and
+ * the virtio config space, too (but first, some resource table overhaul
+ * is needed: move from fixed-sized to variable-length TLV entries).
+ *
+ * For now, the 'flags' member of the resource entry contains the virtio
+ * device id, the 'da' member contains the device features, and 'pa' is
+ * where we need to store the guest features once negotiation completes.
+ * As usual, the 'id' member of this resource contains the index of this
+ * resource type (i.e. is this the first virtio hdr entry, the 2nd, ...).
+ *
+ * Returns 0 on success, or an appropriate error code otherwise
+ */
+static int rproc_handle_virtio_hdr(struct rproc *rproc, struct fw_resource *rsc)
+{
+	struct rproc_vdev *rvdev;
+
+	/* we only support VIRTIO_ID_RPMSG devices for now */
+	if (rsc->flags != VIRTIO_ID_RPMSG) {
+		dev_warn(rproc->dev, "unsupported vdev: %d\n", rsc->flags);
+		return -EINVAL;
+	}
+
+	/* we only support a single vdev per rproc for now */
+	if (rsc->id || rproc->rvdev) {
+		dev_warn(rproc->dev, "redundant vdev entry: %s\n", rsc->name);
+		return -EINVAL;
+	}
+
+	rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL);
+	if (!rvdev)
+		return -ENOMEM;
+
+	/* remember the device features */
+	rvdev->dfeatures = rsc->da;
+
+	rproc->rvdev = rvdev;
+	rvdev->rproc = rproc;
+
+	return 0;
+}
+
+/**
+ * rproc_handle_vring() - handle a vring fw resource
+ * @rproc: the remote processor
+ * @rsc: the vring resource descriptor
+ *
+ * This resource entry requires allocation of non-cacheable memory
+ * for a virtio vring. Currently we only support two vrings per remote
+ * processor, required for the virtio rpmsg device.
+ *
+ * The 'len' member of @rsc should contain the number of buffers this vring
+ * support and 'da' should either contain the device address where
+ * the remote processor is expecting the vring, or indicate that
+ * dynamically allocation of the vring's device address is supported.
+ *
+ * Note: 'da' is currently not handled. This will be revised when the generic
+ * iommu-based DMA API will arrive, or a dynanic & non-iommu use case show
+ * up. Meanwhile, statically-addressed iommu-based images should use
+ * RSC_DEVMEM resource entries to map their require 'da' to the physical
+ * address of their base CMA region.
+ *
+ * Returns 0 on success, or an appropriate error code otherwise
+ */
+static int rproc_handle_vring(struct rproc *rproc, struct fw_resource *rsc)
+{
+	struct device *dev = rproc->dev;
+	struct rproc_vdev *rvdev = rproc->rvdev;
+	dma_addr_t dma;
+	int size, id = rsc->id;
+	void *va;
+
+	/* no vdev is in place ? */
+	if (!rvdev) {
+		dev_err(dev, "vring requested without a virtio dev entry\n");
+		return -EINVAL;
+	}
+
+	/* the firmware must provide the expected queue size */
+	if (!rsc->len) {
+		dev_err(dev, "missing expected queue size\n");
+		return -EINVAL;
+	}
+
+	/* we currently support two vrings per rproc (for rx and tx) */
+	if (id >= ARRAY_SIZE(rvdev->vring)) {
+		dev_err(dev, "%s: invalid vring id %d\n", rsc->name, id);
+		return -EINVAL;
+	}
+
+	/* have we already allocated this vring id ? */
+	if (rvdev->vring[id].len) {
+		dev_err(dev, "%s: duplicated id %d\n", rsc->name, id);
+		return -EINVAL;
+	}
+
+	/* actual size of vring (in bytes) */
+	size = PAGE_ALIGN(vring_size(rsc->len, AMP_VRING_ALIGN));
+
+	/*
+	 * Allocate non-cacheable memory for the vring. In the future
+	 * this call will also configure the IOMMU for us
+	 */
+	va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL);
+	if (!va) {
+		dev_err(dev, "dma_alloc_coherent failed\n");
+		return -ENOMEM;
+	}
+
+	dev_dbg(dev, "vring%d: va %p dma %x qsz %d ring size %x\n", id, va,
+					dma, rsc->len, size);
+
+	rvdev->vring[id].len = rsc->len;
+	rvdev->vring[id].va = va;
+	rvdev->vring[id].dma = dma;
+
+	return 0;
+}
+
+/**
+ * rproc_handle_trace() - handle a shared trace buffer resource
+ * @rproc: the remote processor
+ * @rsc: the trace resource descriptor
+ *
+ * In case the remote processor dumps trace logs into memory,
+ * export it via debugfs.
+ *
+ * Currently, the 'da' member of @rsc should contain the device address
+ * where the remote processor is dumping the traces. Later we could also
+ * support dynamically allocating this address using the generic
+ * DMA API (but currently there isn't a use case for that).
+ *
+ * Returns 0 on success, or an appropriate error code otherwise
+ */
+static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc)
+{
+	struct rproc_mem_entry *trace;
+	struct device *dev = rproc->dev;
+	void *ptr;
+	char name[15];
+
+	/* what's the kernel address of this resource ? */
+	ptr = rproc_da_to_va(rproc, rsc->da, rsc->len);
+	if (!ptr) {
+		dev_err(dev, "erroneous trace resource entry\n");
+		return -EINVAL;
+	}
+
+	trace = kzalloc(sizeof(*trace), GFP_KERNEL);
+	if (!trace) {
+		dev_err(dev, "kzalloc trace failed\n");
+		return -ENOMEM;
+	}
+
+	/* set the trace buffer dma properties */
+	trace->len = rsc->len;
+	trace->va = ptr;
+
+	/* make sure snprintf always null terminates, even if truncating */
+	snprintf(name, sizeof(name), "trace%d", rproc->num_traces);
+
+	/* create the debugfs entry */
+	trace->priv = rproc_create_trace_file(name, rproc, trace);
+	if (!trace->priv) {
+		trace->va = NULL;
+		kfree(trace);
+		return -EINVAL;
+	}
+
+	list_add_tail(&trace->node, &rproc->traces);
+
+	rproc->num_traces++;
+
+	dev_dbg(dev, "%s added: va %p, da 0x%llx, len 0x%x\n", name, ptr,
+						rsc->da, rsc->len);
+
+	return 0;
+}
+
+/**
+ * rproc_handle_devmem() - handle devmem resource entry
+ * @rproc: remote processor handle
+ * @rsc: the devmem resource entry
+ *
+ * Remote processors commonly need to access certain on-chip peripherals.
+ *
+ * Some of these remote processors access memory via an iommu device,
+ * and might require us to configure their iommu before they can access
+ * the on-chip peripherals they need.
+ *
+ * This resource entry is a request to map such a peripheral device.
+ *
+ * These devmem entries will contain the physical address of the device in
+ * the 'pa' member. If a specific device address is expected, then 'da' will
+ * contain it (currently this is the only use case supported). 'len' will
+ * contain the size of the physical region we need to map.
+ *
+ * Currently we just "trust" those devmem entries to contain valid physical
+ * addresses, but this is going to change: we want the implementations to
+ * tell us ranges of physical addresses the firmware is allowed to request,
+ * and not allow firmwares to request access to physical addresses that
+ * are outside those ranges.
+ */
+static int rproc_handle_devmem(struct rproc *rproc, struct fw_resource *rsc)
+{
+	struct rproc_mem_entry *mapping;
+	int ret;
+
+	/* no point in handling this resource without a valid iommu domain */
+	if (!rproc->domain)
+		return -EINVAL;
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping) {
+		dev_err(rproc->dev, "kzalloc mapping failed\n");
+		return -ENOMEM;
+	}
+
+	ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags);
+	if (ret) {
+		dev_err(rproc->dev, "failed to map devmem: %d\n", ret);
+		goto out;
+	}
+
+	/*
+	 * We'll need this info later when we'll want to unmap everything
+	 * (e.g. on shutdown).
+	 *
+	 * We can't trust the remote processor not to change the resource
+	 * table, so we must maintain this info independently.
+	 */
+	mapping->da = rsc->da;
+	mapping->len = rsc->len;
+	list_add_tail(&mapping->node, &rproc->mappings);
+
+	dev_dbg(rproc->dev, "mapped devmem pa 0x%llx, da 0x%llx, len 0x%x\n",
+					rsc->pa, rsc->da, rsc->len);
+
+	return 0;
+
+out:
+	kfree(mapping);
+	return ret;
+}
+
+/**
+ * rproc_handle_carveout() - handle phys contig memory allocation requests
+ * @rproc: rproc handle
+ * @rsc: the resource entry
+ *
+ * This function will handle firmware requests for allocation of physically
+ * contiguous memory regions.
+ *
+ * These request entries should come first in the firmware's resource table,
+ * as other firmware entries might request placing other data objects inside
+ * these memory regions (e.g. data/code segments, trace resource entries, ...).
+ *
+ * Allocating memory this way helps utilizing the reserved physical memory
+ * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
+ * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
+ * pressure is important; it may have a substantial impact on performance.
+ */
+static int rproc_handle_carveout(struct rproc *rproc, struct fw_resource *rsc)
+{
+	struct rproc_mem_entry *carveout, *mapping;
+	struct device *dev = rproc->dev;
+	dma_addr_t dma;
+	void *va;
+	int ret;
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping) {
+		dev_err(dev, "kzalloc mapping failed\n");
+		return -ENOMEM;
+	}
+
+	carveout = kzalloc(sizeof(*carveout), GFP_KERNEL);
+	if (!carveout) {
+		dev_err(dev, "kzalloc carveout failed\n");
+		ret = -ENOMEM;
+		goto free_mapping;
+	}
+
+	va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL);
+	if (!va) {
+		dev_err(dev, "failed to dma alloc carveout: %d\n", rsc->len);
+		ret = -ENOMEM;
+		goto free_carv;
+	}
+
+	dev_dbg(dev, "carveout va %p, dma %x, len 0x%x\n", va, dma, rsc->len);
+
+	/*
+	 * Ok, this is non-standard.
+	 *
+	 * Sometimes we can't rely on the generic iommu-based DMA API
+	 * to dynamically allocate the device address and then set the IOMMU
+	 * tables accordingly, because some remote processors might
+	 * _require_ us to use hard coded device addresses that their
+	 * firmware was compiled with.
+	 *
+	 * In this case, we must use the IOMMU API directly and map
+	 * the memory to the device address as expected by the remote
+	 * processor.
+	 *
+	 * Obviously such remote processor devices should not be configured
+	 * to use the iommu-based DMA API: we expect 'dma' to contain the
+	 * physical address in this case.
+	 */
+	if (rproc->domain) {
+		ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len,
+								rsc->flags);
+		if (ret) {
+			dev_err(dev, "iommu_map failed: %d\n", ret);
+			goto dma_free;
+		}
+
+		/*
+		 * We'll need this info later when we'll want to unmap
+		 * everything (e.g. on shutdown).
+		 *
+		 * We can't trust the remote processor not to change the
+		 * resource table, so we must maintain this info independently.
+		 */
+		mapping->da = rsc->da;
+		mapping->len = rsc->len;
+		list_add_tail(&mapping->node, &rproc->mappings);
+
+		dev_dbg(dev, "carveout mapped 0x%llx to 0x%x\n", rsc->da, dma);
+
+		/*
+		 * Some remote processors might need to know the pa
+		 * even though they are behind an IOMMU. E.g., OMAP4's
+		 * remote M3 processor needs this so it can control
+		 * on-chip hardware accelerators that are not behind
+		 * the IOMMU, and therefor must know the pa.
+		 *
+		 * Generally we don't want to expose physical addresses
+		 * if we don't have to (remote processors are generally
+		 * _not_ trusted), so we might want to do this only for
+		 * remote processor that _must_ have this (e.g. OMAP4's
+		 * dual M3 subsystem).
+		 */
+		rsc->pa = dma;
+	}
+
+	carveout->va = va;
+	carveout->len = rsc->len;
+	carveout->dma = dma;
+	carveout->da = rsc->da;
+
+	list_add_tail(&carveout->node, &rproc->carveouts);
+
+	return 0;
+
+dma_free:
+	dma_free_coherent(dev, rsc->len, va, dma);
+free_carv:
+	kfree(carveout);
+free_mapping:
+	kfree(mapping);
+	return ret;
+}
+
+/* handle firmware resource entries before booting the remote processor */
+static int
+rproc_handle_boot_rsc(struct rproc *rproc, struct fw_resource *rsc, int len)
+{
+	struct device *dev = rproc->dev;
+	int ret = 0;
+
+	while (len >= sizeof(*rsc)) {
+		dev_dbg(dev, "rsc: type %d, da 0x%llx, pa 0x%llx, len 0x%x, "
+			"id %d, name %s, flags %x\n", rsc->type, rsc->da,
+			rsc->pa, rsc->len, rsc->id, rsc->name, rsc->flags);
+
+		switch (rsc->type) {
+		case RSC_CARVEOUT:
+			ret = rproc_handle_carveout(rproc, rsc);
+			break;
+		case RSC_DEVMEM:
+			ret = rproc_handle_devmem(rproc, rsc);
+			break;
+		case RSC_TRACE:
+			ret = rproc_handle_trace(rproc, rsc);
+			break;
+		case RSC_VRING:
+			ret = rproc_handle_vring(rproc, rsc);
+			break;
+		case RSC_VIRTIO_DEV:
+			/* this one is handled early upon registration */
+			break;
+		default:
+			dev_warn(dev, "unsupported resource %d\n", rsc->type);
+			break;
+		}
+
+		if (ret)
+			break;
+
+		rsc++;
+		len -= sizeof(*rsc);
+	}
+
+	return ret;
+}
+
+/* handle firmware resource entries while registering the remote processor */
+static int
+rproc_handle_virtio_rsc(struct rproc *rproc, struct fw_resource *rsc, int len)
+{
+	struct device *dev = rproc->dev;
+	int ret = -ENODEV;
+
+	for (; len >= sizeof(*rsc); rsc++, len -= sizeof(*rsc))
+		if (rsc->type == RSC_VIRTIO_DEV) {
+			dev_dbg(dev, "found vdev %d/%s features %llx\n",
+					rsc->flags, rsc->name, rsc->da);
+			ret = rproc_handle_virtio_hdr(rproc, rsc);
+			break;
+		}
+
+	return ret;
+}
+
+/**
+ * rproc_handle_resources() - find and handle the resource table
+ * @rproc: the rproc handle
+ * @elf_data: the content of the ELF firmware image
+ * @len: firmware size (in bytes)
+ * @handler: function that should be used to handle the resource table
+ *
+ * This function finds the resource table inside the remote processor's
+ * firmware, and invoke a user-supplied handler with it (we have two
+ * possible handlers: one is invoked upon registration of @rproc,
+ * in order to register the supported virito devices, and the other is
+ * invoked when @rproc is actually booted).
+ *
+ * Currently this function fails if a resource table doesn't exist.
+ * This restriction will be removed when we'll start supporting remote
+ * processors that don't need a resource table.
+ */
+static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data,
+				size_t len, rproc_handle_resources_t handler)
+
+{
+	struct elf32_hdr *ehdr;
+	struct elf32_shdr *shdr;
+	const char *name_table;
+	int i, ret = -EINVAL;
+
+	ehdr = (struct elf32_hdr *)elf_data;
+	shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff);
+	name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset;
+
+	/* look for the resource table and handle it */
+	for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+		if (!strcmp(name_table + shdr->sh_name, ".resource_table")) {
+			struct fw_resource *table = (struct fw_resource *)
+						(elf_data + shdr->sh_offset);
+
+			if (shdr->sh_offset + shdr->sh_size > len) {
+				dev_err(rproc->dev,
+					"truncated fw: need 0x%x avail 0x%x\n",
+					shdr->sh_offset + shdr->sh_size, len);
+				ret = -EINVAL;
+			}
+
+			ret = handler(rproc, table, shdr->sh_size);
+
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * rproc_resource_cleanup() - clean up and free all acquired resources
+ * @rproc: rproc handle
+ *
+ * This function will free all resources acquired for @rproc, and it
+ * is called when @rproc shuts down, or just failed booting.
+ */
+static void rproc_resource_cleanup(struct rproc *rproc)
+{
+	struct rproc_mem_entry *entry, *tmp;
+	struct device *dev = rproc->dev;
+	struct rproc_vdev *rvdev = rproc->rvdev;
+	int i;
+
+	/* clean up debugfs trace entries */
+	list_for_each_entry_safe(entry, tmp, &rproc->traces, node) {
+		rproc_remove_trace_file(entry->priv);
+		rproc->num_traces--;
+		list_del(&entry->node);
+		kfree(entry);
+	}
+
+	/* free the coherent memory allocated for the vrings */
+	for (i = 0; rvdev && i < ARRAY_SIZE(rvdev->vring); i++) {
+		int qsz = rvdev->vring[i].len;
+		void *va = rvdev->vring[i].va;
+		int dma = rvdev->vring[i].dma;
+
+		/* virtqueue size is expressed in number of buffers supported */
+		if (qsz) {
+			/* how many bytes does this vring really occupy ? */
+			int size = PAGE_ALIGN(vring_size(qsz, AMP_VRING_ALIGN));
+
+			dma_free_coherent(rproc->dev, size, va, dma);
+
+			rvdev->vring[i].len = 0;
+		}
+	}
+
+	/* clean up carveout allocations */
+	list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) {
+		dma_free_coherent(dev, entry->len, entry->va, entry->dma);
+		list_del(&entry->node);
+		kfree(entry);
+	}
+
+	/* clean up iommu mapping entries */
+	list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) {
+		size_t unmapped;
+
+		unmapped = iommu_unmap(rproc->domain, entry->da, entry->len);
+		if (unmapped != entry->len) {
+			/* nothing much to do besides complaining */
+			dev_err(dev, "failed to unmap %u/%u\n", entry->len,
+								unmapped);
+		}
+
+		list_del(&entry->node);
+		kfree(entry);
+	}
+}
+
+/* make sure this fw image is sane */
+static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw)
+{
+	const char *name = rproc->firmware;
+	struct device *dev = rproc->dev;
+	struct elf32_hdr *ehdr;
+
+	if (!fw) {
+		dev_err(dev, "failed to load %s\n", name);
+		return -EINVAL;
+	}
+
+	if (fw->size < sizeof(struct elf32_hdr)) {
+		dev_err(dev, "Image is too small\n");
+		return -EINVAL;
+	}
+
+	ehdr = (struct elf32_hdr *)fw->data;
+
+	if (fw->size < ehdr->e_shoff + sizeof(struct elf32_shdr)) {
+		dev_err(dev, "Image is too small\n");
+		return -EINVAL;
+	}
+
+	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
+		dev_err(dev, "Image is corrupted (bad magic)\n");
+		return -EINVAL;
+	}
+
+	if (ehdr->e_phnum == 0) {
+		dev_err(dev, "No loadable segments\n");
+		return -EINVAL;
+	}
+
+	if (ehdr->e_phoff > fw->size) {
+		dev_err(dev, "Firmware size is too small\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * take a firmware and boot a remote processor with it.
+ */
+static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw)
+{
+	struct device *dev = rproc->dev;
+	const char *name = rproc->firmware;
+	struct elf32_hdr *ehdr;
+	int ret;
+
+	ret = rproc_fw_sanity_check(rproc, fw);
+	if (ret)
+		return ret;
+
+	ehdr = (struct elf32_hdr *)fw->data;
+
+	dev_info(dev, "Booting fw image %s, size %d\n", name, fw->size);
+
+	/*
+	 * if enabling an IOMMU isn't relevant for this rproc, this is
+	 * just a nop
+	 */
+	ret = rproc_enable_iommu(rproc);
+	if (ret) {
+		dev_err(dev, "can't enable iommu: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * The ELF entry point is the rproc's boot addr (though this is not
+	 * a configurable property of all remote processors: some will always
+	 * boot at a specific hardcoded address).
+	 */
+	rproc->bootaddr = ehdr->e_entry;
+
+	/* handle fw resources which are required to boot rproc */
+	ret = rproc_handle_resources(rproc, fw->data, fw->size,
+						rproc_handle_boot_rsc);
+	if (ret) {
+		dev_err(dev, "Failed to process resources: %d\n", ret);
+		goto clean_up;
+	}
+
+	/* load the ELF segments to memory */
+	ret = rproc_load_segments(rproc, fw->data, fw->size);
+	if (ret) {
+		dev_err(dev, "Failed to load program segments: %d\n", ret);
+		goto clean_up;
+	}
+
+	/* power up the remote processor */
+	ret = rproc->ops->start(rproc);
+	if (ret) {
+		dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret);
+		goto clean_up;
+	}
+
+	rproc->state = RPROC_RUNNING;
+
+	dev_info(dev, "remote processor %s is now up\n", rproc->name);
+
+	return 0;
+
+clean_up:
+	rproc_resource_cleanup(rproc);
+	rproc_disable_iommu(rproc);
+	return ret;
+}
+
+/*
+ * take a firmware and look for virtio devices to register.
+ *
+ * Note: this function is called asynchronously upon registration of the
+ * remote processor (so we must wait until it completes before we try
+ * to unregister the device. one other option is just to use kref here,
+ * that might be cleaner).
+ */
+static void rproc_fw_config_virtio(const struct firmware *fw, void *context)
+{
+	struct rproc *rproc = context;
+	struct device *dev = rproc->dev;
+	int ret;
+
+	if (rproc_fw_sanity_check(rproc, fw) < 0)
+		goto out;
+
+	/* does the fw supports any virtio devices ? */
+	ret = rproc_handle_resources(rproc, fw->data, fw->size,
+						rproc_handle_virtio_rsc);
+	if (ret) {
+		dev_info(dev, "No fw virtio device was found\n");
+		goto out;
+	}
+
+	/* add the virtio device (currently only rpmsg vdevs are supported) */
+	ret = rproc_add_rpmsg_vdev(rproc);
+	if (ret)
+		goto out;
+
+out:
+	if (fw)
+		release_firmware(fw);
+	/* allow rproc_unregister() contexts, if any, to proceed */
+	complete_all(&rproc->firmware_loading_complete);
+}
+
+/**
+ * rproc_boot() - boot a remote processor
+ * @rproc: handle of a remote processor
+ *
+ * Boot a remote processor (i.e. load its firmware, power it on, ...).
+ *
+ * If the remote processor is already powered on, this function immediately
+ * returns (successfully).
+ *
+ * Returns 0 on success, and an appropriate error value otherwise.
+ */
+int rproc_boot(struct rproc *rproc)
+{
+	const struct firmware *firmware_p;
+	struct device *dev;
+	int ret;
+
+	if (!rproc) {
+		pr_err("invalid rproc handle\n");
+		return -EINVAL;
+	}
+
+	dev = rproc->dev;
+
+	ret = mutex_lock_interruptible(&rproc->lock);
+	if (ret) {
+		dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret);
+		return ret;
+	}
+
+	/* loading a firmware is required */
+	if (!rproc->firmware) {
+		dev_err(dev, "%s: no firmware to load\n", __func__);
+		ret = -EINVAL;
+		goto unlock_mutex;
+	}
+
+	/* prevent underlying implementation from being removed */
+	if (!try_module_get(dev->driver->owner)) {
+		dev_err(dev, "%s: can't get owner\n", __func__);
+		ret = -EINVAL;
+		goto unlock_mutex;
+	}
+
+	/* skip the boot process if rproc is already powered up */
+	if (atomic_inc_return(&rproc->power) > 1) {
+		ret = 0;
+		goto unlock_mutex;
+	}
+
+	dev_info(dev, "powering up %s\n", rproc->name);
+
+	/* load firmware */
+	ret = request_firmware(&firmware_p, rproc->firmware, dev);
+	if (ret < 0) {
+		dev_err(dev, "request_firmware failed: %d\n", ret);
+		goto downref_rproc;
+	}
+
+	ret = rproc_fw_boot(rproc, firmware_p);
+
+	release_firmware(firmware_p);
+
+downref_rproc:
+	if (ret) {
+		module_put(dev->driver->owner);
+		atomic_dec(&rproc->power);
+	}
+unlock_mutex:
+	mutex_unlock(&rproc->lock);
+	return ret;
+}
+EXPORT_SYMBOL(rproc_boot);
+
+/**
+ * rproc_shutdown() - power off the remote processor
+ * @rproc: the remote processor
+ *
+ * Power off a remote processor (previously booted with rproc_boot()).
+ *
+ * In case @rproc is still being used by an additional user(s), then
+ * this function will just decrement the power refcount and exit,
+ * without really powering off the device.
+ *
+ * Every call to rproc_boot() must (eventually) be accompanied by a call
+ * to rproc_shutdown(). Calling rproc_shutdown() redundantly is a bug.
+ *
+ * Notes:
+ * - we're not decrementing the rproc's refcount, only the power refcount.
+ *   which means that the @rproc handle stays valid even after rproc_shutdown()
+ *   returns, and users can still use it with a subsequent rproc_boot(), if
+ *   needed.
+ * - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly
+ *   because rproc_shutdown() _does not_ decrement the refcount of @rproc.
+ *   To decrement the refcount of @rproc, use rproc_put() (but _only_ if
+ *   you acquired @rproc using rproc_get_by_name()).
+ */
+void rproc_shutdown(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev;
+	int ret;
+
+	ret = mutex_lock_interruptible(&rproc->lock);
+	if (ret) {
+		dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret);
+		return;
+	}
+
+	/* if the remote proc is still needed, bail out */
+	if (!atomic_dec_and_test(&rproc->power))
+		goto out;
+
+	/* power off the remote processor */
+	ret = rproc->ops->stop(rproc);
+	if (ret) {
+		atomic_inc(&rproc->power);
+		dev_err(dev, "can't stop rproc: %d\n", ret);
+		goto out;
+	}
+
+	/* clean up all acquired resources */
+	rproc_resource_cleanup(rproc);
+
+	rproc_disable_iommu(rproc);
+
+	rproc->state = RPROC_OFFLINE;
+
+	dev_info(dev, "stopped remote processor %s\n", rproc->name);
+
+out:
+	mutex_unlock(&rproc->lock);
+	if (!ret)
+		module_put(dev->driver->owner);
+}
+EXPORT_SYMBOL(rproc_shutdown);
+
+/**
+ * rproc_release() - completely deletes the existence of a remote processor
+ * @kref: the rproc's kref
+ *
+ * This function should _never_ be called directly.
+ *
+ * The only reasonable location to use it is as an argument when kref_put'ing
+ * @rproc's refcount.
+ *
+ * This way it will be called when no one holds a valid pointer to this @rproc
+ * anymore (and obviously after it is removed from the rprocs klist).
+ *
+ * Note: this function is not static because rproc_vdev_release() needs it when
+ * it decrements @rproc's refcount.
+ */
+void rproc_release(struct kref *kref)
+{
+	struct rproc *rproc = container_of(kref, struct rproc, refcount);
+
+	dev_info(rproc->dev, "removing %s\n", rproc->name);
+
+	rproc_delete_debug_dir(rproc);
+
+	/* at this point no one holds a reference to rproc anymore */
+	kfree(rproc);
+}
+
+/* will be called when an rproc is added to the rprocs klist */
+static void klist_rproc_get(struct klist_node *n)
+{
+	struct rproc *rproc = container_of(n, struct rproc, node);
+
+	kref_get(&rproc->refcount);
+}
+
+/* will be called when an rproc is removed from the rprocs klist */
+static void klist_rproc_put(struct klist_node *n)
+{
+	struct rproc *rproc = container_of(n, struct rproc, node);
+
+	kref_put(&rproc->refcount, rproc_release);
+}
+
+static struct rproc *next_rproc(struct klist_iter *i)
+{
+	struct klist_node *n;
+
+	n = klist_next(i);
+	if (!n)
+		return NULL;
+
+	return container_of(n, struct rproc, node);
+}
+
+/**
+ * rproc_get_by_name() - find a remote processor by name and boot it
+ * @name: name of the remote processor
+ *
+ * Finds an rproc handle using the remote processor's name, and then
+ * boot it. If it's already powered on, then just immediately return
+ * (successfully).
+ *
+ * Returns the rproc handle on success, and NULL on failure.
+ *
+ * This function increments the remote processor's refcount, so always
+ * use rproc_put() to decrement it back once rproc isn't needed anymore.
+ *
+ * Note: currently this function (and its counterpart rproc_put()) are not
+ * used anymore by the rpmsg subsystem. We need to scrutinize the use cases
+ * that still need them, and see if we can migrate them to use the non
+ * name-based boot/shutdown interface.
+ */
+struct rproc *rproc_get_by_name(const char *name)
+{
+	struct rproc *rproc;
+	struct klist_iter i;
+	int ret;
+
+	/* find the remote processor, and upref its refcount */
+	klist_iter_init(&rprocs, &i);
+	while ((rproc = next_rproc(&i)) != NULL)
+		if (!strcmp(rproc->name, name)) {
+			kref_get(&rproc->refcount);
+			break;
+		}
+	klist_iter_exit(&i);
+
+	/* can't find this rproc ? */
+	if (!rproc) {
+		pr_err("can't find remote processor %s\n", name);
+		return NULL;
+	}
+
+	ret = rproc_boot(rproc);
+	if (ret < 0) {
+		kref_put(&rproc->refcount, rproc_release);
+		return NULL;
+	}
+
+	return rproc;
+}
+EXPORT_SYMBOL(rproc_get_by_name);
+
+/**
+ * rproc_put() - decrement the refcount of a remote processor, and shut it down
+ * @rproc: the remote processor
+ *
+ * This function tries to shutdown @rproc, and it then decrements its
+ * refcount.
+ *
+ * After this function returns, @rproc may _not_ be used anymore, and its
+ * handle should be considered invalid.
+ *
+ * This function should be called _iff_ the @rproc handle was grabbed by
+ * calling rproc_get_by_name().
+ */
+void rproc_put(struct rproc *rproc)
+{
+	/* try to power off the remote processor */
+	rproc_shutdown(rproc);
+
+	/* downref rproc's refcount */
+	kref_put(&rproc->refcount, rproc_release);
+}
+EXPORT_SYMBOL(rproc_put);
+
+/**
+ * rproc_register() - register a remote processor
+ * @rproc: the remote processor handle to register
+ *
+ * Registers @rproc with the remoteproc framework, after it has been
+ * allocated with rproc_alloc().
+ *
+ * This is called by the platform-specific rproc implementation, whenever
+ * a new remote processor device is probed.
+ *
+ * Returns 0 on success and an appropriate error code otherwise.
+ *
+ * Note: this function initiates an asynchronous firmware loading
+ * context, which will look for virtio devices supported by the rproc's
+ * firmware.
+ *
+ * If found, those virtio devices will be created and added, so as a result
+ * of registering this remote processor, additional virtio drivers will be
+ * probed.
+ *
+ * Currently, though, we only support a single RPMSG virtio vdev per remote
+ * processor.
+ */
+int rproc_register(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev;
+	int ret = 0;
+
+	/* expose to rproc_get_by_name users */
+	klist_add_tail(&rproc->node, &rprocs);
+
+	dev_info(rproc->dev, "%s is available\n", rproc->name);
+
+	dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n");
+	dev_info(dev, "THE BINARY FORMAT IS NOT YET FINALIZED, and backward compatibility isn't yet guaranteed.\n");
+
+	/* create debugfs entries */
+	rproc_create_debug_dir(rproc);
+
+	/* rproc_unregister() calls must wait until async loader completes */
+	init_completion(&rproc->firmware_loading_complete);
+
+	/*
+	 * We must retrieve early virtio configuration info from
+	 * the firmware (e.g. whether to register a virtio rpmsg device,
+	 * what virtio features does it support, ...).
+	 *
+	 * We're initiating an asynchronous firmware loading, so we can
+	 * be built-in kernel code, without hanging the boot process.
+	 */
+	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+					rproc->firmware, dev, GFP_KERNEL,
+					rproc, rproc_fw_config_virtio);
+	if (ret < 0) {
+		dev_err(dev, "request_firmware_nowait failed: %d\n", ret);
+		complete_all(&rproc->firmware_loading_complete);
+		klist_remove(&rproc->node);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(rproc_register);
+
+/**
+ * rproc_alloc() - allocate a remote processor handle
+ * @dev: the underlying device
+ * @name: name of this remote processor
+ * @ops: platform-specific handlers (mainly start/stop)
+ * @firmware: name of firmware file to load
+ * @len: length of private data needed by the rproc driver (in bytes)
+ *
+ * Allocates a new remote processor handle, but does not register
+ * it yet.
+ *
+ * This function should be used by rproc implementations during initialization
+ * of the remote processor.
+ *
+ * After creating an rproc handle using this function, and when ready,
+ * implementations should then call rproc_register() to complete
+ * the registration of the remote processor.
+ *
+ * On success the new rproc is returned, and on failure, NULL.
+ *
+ * Note: _never_ directly deallocate @rproc, even if it was not registered
+ * yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free().
+ */
+struct rproc *rproc_alloc(struct device *dev, const char *name,
+				const struct rproc_ops *ops,
+				const char *firmware, int len)
+{
+	struct rproc *rproc;
+
+	if (!dev || !name || !ops)
+		return NULL;
+
+	rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL);
+	if (!rproc) {
+		dev_err(dev, "%s: kzalloc failed\n", __func__);
+		return NULL;
+	}
+
+	rproc->dev = dev;
+	rproc->name = name;
+	rproc->ops = ops;
+	rproc->firmware = firmware;
+	rproc->priv = &rproc[1];
+
+	atomic_set(&rproc->power, 0);
+
+	kref_init(&rproc->refcount);
+
+	mutex_init(&rproc->lock);
+
+	INIT_LIST_HEAD(&rproc->carveouts);
+	INIT_LIST_HEAD(&rproc->mappings);
+	INIT_LIST_HEAD(&rproc->traces);
+
+	rproc->state = RPROC_OFFLINE;
+
+	return rproc;
+}
+EXPORT_SYMBOL(rproc_alloc);
+
+/**
+ * rproc_free() - free an rproc handle that was allocated by rproc_alloc
+ * @rproc: the remote processor handle
+ *
+ * This function should _only_ be used if @rproc was only allocated,
+ * but not registered yet.
+ *
+ * If @rproc was already successfully registered (by calling rproc_register()),
+ * then use rproc_unregister() instead.
+ */
+void rproc_free(struct rproc *rproc)
+{
+	kfree(rproc);
+}
+EXPORT_SYMBOL(rproc_free);
+
+/**
+ * rproc_unregister() - unregister a remote processor
+ * @rproc: rproc handle to unregister
+ *
+ * Unregisters a remote processor, and decrements its refcount.
+ * If its refcount drops to zero, then @rproc will be freed. If not,
+ * it will be freed later once the last reference is dropped.
+ *
+ * This function should be called when the platform specific rproc
+ * implementation decides to remove the rproc device. it should
+ * _only_ be called if a previous invocation of rproc_register()
+ * has completed successfully.
+ *
+ * After rproc_unregister() returns, @rproc is _not_ valid anymore and
+ * it shouldn't be used. More specifically, don't call rproc_free()
+ * or try to directly free @rproc after rproc_unregister() returns;
+ * none of these are needed, and calling them is a bug.
+ *
+ * Returns 0 on success and -EINVAL if @rproc isn't valid.
+ */
+int rproc_unregister(struct rproc *rproc)
+{
+	if (!rproc)
+		return -EINVAL;
+
+	/* if rproc is just being registered, wait */
+	wait_for_completion(&rproc->firmware_loading_complete);
+
+	/* was an rpmsg vdev created ? */
+	if (rproc->rvdev)
+		rproc_remove_rpmsg_vdev(rproc);
+
+	klist_remove(&rproc->node);
+
+	kref_put(&rproc->refcount, rproc_release);
+
+	return 0;
+}
+EXPORT_SYMBOL(rproc_unregister);
+
+static int __init remoteproc_init(void)
+{
+	rproc_init_debugfs();
+	return 0;
+}
+module_init(remoteproc_init);
+
+static void __exit remoteproc_exit(void)
+{
+	rproc_exit_debugfs();
+}
+module_exit(remoteproc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Generic Remote Processor Framework");
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
new file mode 100644
index 0000000..70277a5
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -0,0 +1,179 @@
+/*
+ * Remote Processor Framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Mark Grosen <mgrosen@ti.com>
+ * Brian Swetland <swetland@google.com>
+ * Fernando Guzman Lugo <fernando.lugo@ti.com>
+ * Suman Anna <s-anna@ti.com>
+ * Robert Tivy <rtivy@ti.com>
+ * Armando Uribe De Leon <x0095078@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.
+ */
+
+#define pr_fmt(fmt)    "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/remoteproc.h>
+#include <linux/device.h>
+
+/* remoteproc debugfs parent dir */
+static struct dentry *rproc_dbg;
+
+/*
+ * Some remote processors may support dumping trace logs into a shared
+ * memory buffer. We expose this trace buffer using debugfs, so users
+ * can easily tell what's going on remotely.
+ *
+ * We will most probably improve the rproc tracing facilities later on,
+ * but this kind of lightweight and simple mechanism is always good to have,
+ * as it provides very early tracing with little to no dependencies at all.
+ */
+static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf,
+						size_t count, loff_t *ppos)
+{
+	struct rproc_mem_entry *trace = filp->private_data;
+	int len = strnlen(trace->va, trace->len);
+
+	return simple_read_from_buffer(userbuf, count, ppos, trace->va, len);
+}
+
+static int rproc_open_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+
+	return 0;
+}
+
+static const struct file_operations trace_rproc_ops = {
+	.read = rproc_trace_read,
+	.open = rproc_open_generic,
+	.llseek	= generic_file_llseek,
+};
+
+/*
+ * A state-to-string lookup table, for exposing a human readable state
+ * via debugfs. Always keep in sync with enum rproc_state
+ */
+static const char * const rproc_state_string[] = {
+	"offline",
+	"suspended",
+	"running",
+	"crashed",
+	"invalid",
+};
+
+/* expose the state of the remote processor via debugfs */
+static ssize_t rproc_state_read(struct file *filp, char __user *userbuf,
+						size_t count, loff_t *ppos)
+{
+	struct rproc *rproc = filp->private_data;
+	unsigned int state;
+	char buf[30];
+	int i;
+
+	state = rproc->state > RPROC_LAST ? RPROC_LAST : rproc->state;
+
+	i = snprintf(buf, 30, "%.28s (%d)\n", rproc_state_string[state],
+							rproc->state);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, i);
+}
+
+static const struct file_operations rproc_state_ops = {
+	.read = rproc_state_read,
+	.open = rproc_open_generic,
+	.llseek	= generic_file_llseek,
+};
+
+/* expose the name of the remote processor via debugfs */
+static ssize_t rproc_name_read(struct file *filp, char __user *userbuf,
+						size_t count, loff_t *ppos)
+{
+	struct rproc *rproc = filp->private_data;
+	/* need room for the name, a newline and a terminating null */
+	char buf[100];
+	int i;
+
+	i = snprintf(buf, sizeof(buf), "%.98s\n", rproc->name);
+
+	return simple_read_from_buffer(userbuf, count, ppos, buf, i);
+}
+
+static const struct file_operations rproc_name_ops = {
+	.read = rproc_name_read,
+	.open = rproc_open_generic,
+	.llseek	= generic_file_llseek,
+};
+
+void rproc_remove_trace_file(struct dentry *tfile)
+{
+	debugfs_remove(tfile);
+}
+
+struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
+					struct rproc_mem_entry *trace)
+{
+	struct dentry *tfile;
+
+	tfile = debugfs_create_file(name, 0400, rproc->dbg_dir,
+						trace, &trace_rproc_ops);
+	if (!tfile) {
+		dev_err(rproc->dev, "failed to create debugfs trace entry\n");
+		return NULL;
+	}
+
+	return tfile;
+}
+
+void rproc_delete_debug_dir(struct rproc *rproc)
+{
+	if (!rproc->dbg_dir)
+		return;
+
+	debugfs_remove_recursive(rproc->dbg_dir);
+}
+
+void rproc_create_debug_dir(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev;
+
+	if (!rproc_dbg)
+		return;
+
+	rproc->dbg_dir = debugfs_create_dir(dev_name(dev), rproc_dbg);
+	if (!rproc->dbg_dir)
+		return;
+
+	debugfs_create_file("name", 0400, rproc->dbg_dir,
+					rproc, &rproc_name_ops);
+	debugfs_create_file("state", 0400, rproc->dbg_dir,
+					rproc, &rproc_state_ops);
+}
+
+void __init rproc_init_debugfs(void)
+{
+	if (debugfs_initialized()) {
+		rproc_dbg = debugfs_create_dir(KBUILD_MODNAME, NULL);
+		if (!rproc_dbg)
+			pr_err("can't create debugfs dir\n");
+	}
+}
+
+void __exit rproc_exit_debugfs(void)
+{
+	if (rproc_dbg)
+		debugfs_remove(rproc_dbg);
+}
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
new file mode 100644
index 0000000..8b2fc40
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -0,0 +1,44 @@
+/*
+ * Remote processor framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * 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 REMOTEPROC_INTERNAL_H
+#define REMOTEPROC_INTERNAL_H
+
+#include <linux/irqreturn.h>
+
+struct rproc;
+
+/* from remoteproc_core.c */
+void rproc_release(struct kref *kref);
+irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id);
+
+/* from remoteproc_rpmsg.c */
+int rproc_add_rpmsg_vdev(struct rproc *);
+void rproc_remove_rpmsg_vdev(struct rproc *rproc);
+
+/* from remoteproc_debugfs.c */
+void rproc_remove_trace_file(struct dentry *tfile);
+struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc,
+					struct rproc_mem_entry *trace);
+void rproc_delete_debug_dir(struct rproc *rproc);
+void rproc_create_debug_dir(struct rproc *rproc);
+void rproc_init_debugfs(void);
+void rproc_exit_debugfs(void);
+
+#endif /* REMOTEPROC_INTERNAL_H */
diff --git a/drivers/remoteproc/remoteproc_rpmsg.c b/drivers/remoteproc/remoteproc_rpmsg.c
new file mode 100644
index 0000000..4f73e81
--- /dev/null
+++ b/drivers/remoteproc/remoteproc_rpmsg.c
@@ -0,0 +1,299 @@
+/*
+ * Remote processor messaging transport (OMAP platform-specific bits)
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/export.h>
+#include <linux/remoteproc.h>
+#include <linux/rpmsg.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_ring.h>
+#include <linux/err.h>
+#include <linux/kref.h>
+#include <linux/slab.h>
+
+#include "remoteproc_internal.h"
+
+/**
+ * struct rproc_virtio_vq_info - virtqueue state
+ * @vq_id: a unique index of this virtqueue (unique for this @rproc)
+ * @rproc: handle to the remote processor
+ *
+ * Such a struct will be maintained for every virtqueue we're
+ * using to communicate with the remote processor
+ */
+struct rproc_virtio_vq_info {
+	__u16 vq_id;
+	struct rproc *rproc;
+};
+
+/* kick the remote processor, and let it know which virtqueue to poke at */
+static void rproc_virtio_notify(struct virtqueue *vq)
+{
+	struct rproc_virtio_vq_info *rpvq = vq->priv;
+	struct rproc *rproc = rpvq->rproc;
+
+	dev_dbg(rproc->dev, "kicking vq id: %d\n", rpvq->vq_id);
+
+	rproc->ops->kick(rproc, rpvq->vq_id);
+}
+
+/**
+ * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted
+ * @rproc: handle to the remote processor
+ * @vq_id: index of the signalled virtqueue
+ *
+ * This function should be called by the platform-specific rproc driver,
+ * when the remote processor signals that a specific virtqueue has pending
+ * messages available.
+ *
+ * Returns IRQ_NONE if no message was found in the @vq_id virtqueue,
+ * and otherwise returns IRQ_HANDLED.
+ */
+irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id)
+{
+	return vring_interrupt(0, rproc->rvdev->vq[vq_id]);
+}
+EXPORT_SYMBOL(rproc_vq_interrupt);
+
+static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
+				    unsigned id,
+				    void (*callback)(struct virtqueue *vq),
+				    const char *name)
+{
+	struct rproc *rproc = vdev_to_rproc(vdev);
+	struct rproc_vdev *rvdev = rproc->rvdev;
+	struct rproc_virtio_vq_info *rpvq;
+	struct virtqueue *vq;
+	void *addr;
+	int ret, len;
+
+	rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL);
+	if (!rpvq)
+		return ERR_PTR(-ENOMEM);
+
+	rpvq->rproc = rproc;
+	rpvq->vq_id = id;
+
+	addr = rvdev->vring[id].va;
+	len = rvdev->vring[id].len;
+
+	dev_dbg(rproc->dev, "vring%d: va %p qsz %d\n", id, addr, len);
+
+	/*
+	 * Create the new vq, and tell virtio we're not interested in
+	 * the 'weak' smp barriers, since we're talking with a real device.
+	 */
+	vq = vring_new_virtqueue(len, AMP_VRING_ALIGN, vdev, false, addr,
+					rproc_virtio_notify, callback, name);
+	if (!vq) {
+		dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name);
+		ret = -ENOMEM;
+		goto free_rpvq;
+	}
+
+	rvdev->vq[id] = vq;
+	vq->priv = rpvq;
+
+	return vq;
+
+free_rpvq:
+	kfree(rpvq);
+	return ERR_PTR(ret);
+}
+
+static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+{
+	struct virtqueue *vq, *n;
+	struct rproc *rproc = vdev_to_rproc(vdev);
+
+	list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
+		struct rproc_virtio_vq_info *rpvq = vq->priv;
+		vring_del_virtqueue(vq);
+		kfree(rpvq);
+	}
+
+	/* power down the remote processor */
+	rproc_shutdown(rproc);
+}
+
+static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+		       struct virtqueue *vqs[],
+		       vq_callback_t *callbacks[],
+		       const char *names[])
+{
+	struct rproc *rproc = vdev_to_rproc(vdev);
+	int i, ret;
+
+	/* we maintain two virtqueues per remote processor (for RX and TX) */
+	if (nvqs != 2)
+		return -EINVAL;
+
+	/* boot the remote processor */
+	ret = rproc_boot(rproc);
+	if (ret) {
+		dev_err(rproc->dev, "rproc_boot() failed %d\n", ret);
+		goto error;
+	}
+
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
+		if (IS_ERR(vqs[i])) {
+			ret = PTR_ERR(vqs[i]);
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	rproc_virtio_del_vqs(vdev);
+	return ret;
+}
+
+/*
+ * We don't support yet real virtio status semantics.
+ *
+ * The plan is to provide this via the VIRTIO HDR resource entry
+ * which is part of the firmware: this way the remote processor
+ * will be able to access the status values as set by us.
+ */
+static u8 rproc_virtio_get_status(struct virtio_device *vdev)
+{
+	return 0;
+}
+
+static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status)
+{
+	dev_dbg(&vdev->dev, "new status: %d\n", status);
+}
+
+static void rproc_virtio_reset(struct virtio_device *vdev)
+{
+	dev_dbg(&vdev->dev, "reset !\n");
+}
+
+/* provide the vdev features as retrieved from the firmware */
+static u32 rproc_virtio_get_features(struct virtio_device *vdev)
+{
+	struct rproc *rproc = vdev_to_rproc(vdev);
+
+	/* we only support a single vdev device for now */
+	return rproc->rvdev->dfeatures;
+}
+
+static void rproc_virtio_finalize_features(struct virtio_device *vdev)
+{
+	struct rproc *rproc = vdev_to_rproc(vdev);
+
+	/* Give virtio_ring a chance to accept features */
+	vring_transport_features(vdev);
+
+	/*
+	 * Remember the finalized features of our vdev, and provide it
+	 * to the remote processor once it is powered on.
+	 *
+	 * Similarly to the status field, we don't expose yet the negotiated
+	 * features to the remote processors at this point. This will be
+	 * fixed as part of a small resource table overhaul and then an
+	 * extension of the virtio resource entries.
+	 */
+	rproc->rvdev->gfeatures = vdev->features[0];
+}
+
+static struct virtio_config_ops rproc_virtio_config_ops = {
+	.get_features	= rproc_virtio_get_features,
+	.finalize_features = rproc_virtio_finalize_features,
+	.find_vqs	= rproc_virtio_find_vqs,
+	.del_vqs	= rproc_virtio_del_vqs,
+	.reset		= rproc_virtio_reset,
+	.set_status	= rproc_virtio_set_status,
+	.get_status	= rproc_virtio_get_status,
+};
+
+/*
+ * This function is called whenever vdev is released, and is responsible
+ * to decrement the remote processor's refcount taken when vdev was
+ * added.
+ *
+ * Never call this function directly; it will be called by the driver
+ * core when needed.
+ */
+static void rproc_vdev_release(struct device *dev)
+{
+	struct virtio_device *vdev = dev_to_virtio(dev);
+	struct rproc *rproc = vdev_to_rproc(vdev);
+
+	kref_put(&rproc->refcount, rproc_release);
+}
+
+/**
+ * rproc_add_rpmsg_vdev() - create an rpmsg virtio device
+ * @rproc: the rproc handle
+ *
+ * This function is called if virtio rpmsg support was found in the
+ * firmware of the remote processor.
+ *
+ * Today we only support creating a single rpmsg vdev (virtio device),
+ * but the plan is to remove this limitation. At that point this interface
+ * will be revised/extended.
+ */
+int rproc_add_rpmsg_vdev(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev;
+	struct rproc_vdev *rvdev = rproc->rvdev;
+	int ret;
+
+	rvdev->vdev.id.device	= VIRTIO_ID_RPMSG,
+	rvdev->vdev.config	= &rproc_virtio_config_ops,
+	rvdev->vdev.dev.parent	= dev;
+	rvdev->vdev.dev.release	= rproc_vdev_release;
+
+	/*
+	 * We're indirectly making a non-temporary copy of the rproc pointer
+	 * here, because drivers probed with this vdev will indirectly
+	 * access the wrapping rproc.
+	 *
+	 * Therefore we must increment the rproc refcount here, and decrement
+	 * it _only_ when the vdev is released.
+	 */
+	kref_get(&rproc->refcount);
+
+	ret = register_virtio_device(&rvdev->vdev);
+	if (ret) {
+		kref_put(&rproc->refcount, rproc_release);
+		dev_err(dev, "failed to register vdev: %d\n", ret);
+	}
+
+	return ret;
+}
+
+/**
+ * rproc_remove_rpmsg_vdev() - remove an rpmsg vdev device
+ * @rproc: the rproc handle
+ *
+ * This function is called whenever @rproc is removed _iff_ an rpmsg
+ * vdev was created beforehand.
+ */
+void rproc_remove_rpmsg_vdev(struct rproc *rproc)
+{
+	struct rproc_vdev *rvdev = rproc->rvdev;
+
+	unregister_virtio_device(&rvdev->vdev);
+}
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
new file mode 100644
index 0000000..32aead6
--- /dev/null
+++ b/drivers/rpmsg/Kconfig
@@ -0,0 +1,10 @@
+menu "Rpmsg drivers (EXPERIMENTAL)"
+
+# RPMSG always gets selected by whoever wants it
+config RPMSG
+	tristate
+	select VIRTIO
+	select VIRTIO_RING
+	depends on EXPERIMENTAL
+
+endmenu
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
new file mode 100644
index 0000000..7617fcb
--- /dev/null
+++ b/drivers/rpmsg/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
new file mode 100644
index 0000000..8980ac2
--- /dev/null
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -0,0 +1,1026 @@
+/*
+ * Virtio-based remote processor messaging bus
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/rpmsg.h>
+#include <linux/mutex.h>
+
+/**
+ * struct virtproc_info - virtual remote processor state
+ * @vdev:	the virtio device
+ * @rvq:	rx virtqueue
+ * @svq:	tx virtqueue
+ * @rbufs:	kernel address of rx buffers
+ * @sbufs:	kernel address of tx buffers
+ * @last_sbuf:	index of last tx buffer used
+ * @bufs_dma:	dma base addr of the buffers
+ * @tx_lock:	protects svq, sbufs and sleepers, to allow concurrent senders.
+ *		sending a message might require waking up a dozing remote
+ *		processor, which involves sleeping, hence the mutex.
+ * @endpoints:	idr of local endpoints, allows fast retrieval
+ * @endpoints_lock: lock of the endpoints set
+ * @sendq:	wait queue of sending contexts waiting for a tx buffers
+ * @sleepers:	number of senders that are waiting for a tx buffer
+ * @ns_ept:	the bus's name service endpoint
+ *
+ * This structure stores the rpmsg state of a given virtio remote processor
+ * device (there might be several virtio proc devices for each physical
+ * remote processor).
+ */
+struct virtproc_info {
+	struct virtio_device *vdev;
+	struct virtqueue *rvq, *svq;
+	void *rbufs, *sbufs;
+	int last_sbuf;
+	dma_addr_t bufs_dma;
+	struct mutex tx_lock;
+	struct idr endpoints;
+	struct mutex endpoints_lock;
+	wait_queue_head_t sendq;
+	atomic_t sleepers;
+	struct rpmsg_endpoint *ns_ept;
+};
+
+/**
+ * struct rpmsg_channel_info - internal channel info representation
+ * @name: name of service
+ * @src: local address
+ * @dst: destination address
+ */
+struct rpmsg_channel_info {
+	char name[RPMSG_NAME_SIZE];
+	u32 src;
+	u32 dst;
+};
+
+#define to_rpmsg_channel(d) container_of(d, struct rpmsg_channel, dev)
+#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
+
+/*
+ * We're allocating 512 buffers of 512 bytes for communications, and then
+ * using the first 256 buffers for RX, and the last 256 buffers for TX.
+ *
+ * Each buffer will have 16 bytes for the msg header and 496 bytes for
+ * the payload.
+ *
+ * This will require a total space of 256KB for the buffers.
+ *
+ * We might also want to add support for user-provided buffers in time.
+ * This will allow bigger buffer size flexibility, and can also be used
+ * to achieve zero-copy messaging.
+ *
+ * Note that these numbers are purely a decision of this driver - we
+ * can change this without changing anything in the firmware of the remote
+ * processor.
+ */
+#define RPMSG_NUM_BUFS		(512)
+#define RPMSG_BUF_SIZE		(512)
+#define RPMSG_TOTAL_BUF_SPACE	(RPMSG_NUM_BUFS * RPMSG_BUF_SIZE)
+
+/*
+ * Local addresses are dynamically allocated on-demand.
+ * We do not dynamically assign addresses from the low 1024 range,
+ * in order to reserve that address range for predefined services.
+ */
+#define RPMSG_RESERVED_ADDRESSES	(1024)
+
+/* Address 53 is reserved for advertising remote services */
+#define RPMSG_NS_ADDR			(53)
+
+/* sysfs show configuration fields */
+#define rpmsg_show_attr(field, path, format_string)			\
+static ssize_t								\
+field##_show(struct device *dev,					\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);		\
+									\
+	return sprintf(buf, format_string, rpdev->path);		\
+}
+
+/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
+rpmsg_show_attr(name, id.name, "%s\n");
+rpmsg_show_attr(src, src, "0x%x\n");
+rpmsg_show_attr(dst, dst, "0x%x\n");
+rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
+
+/*
+ * Unique (and free running) index for rpmsg devices.
+ *
+ * Yeah, we're not recycling those numbers (yet?). will be easy
+ * to change if/when we want to.
+ */
+static unsigned int rpmsg_dev_index;
+
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+
+	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
+}
+
+static struct device_attribute rpmsg_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_RO(dst),
+	__ATTR_RO(src),
+	__ATTR_RO(announce),
+	__ATTR_NULL
+};
+
+/* rpmsg devices and drivers are matched using the service name */
+static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev,
+				  const struct rpmsg_device_id *id)
+{
+	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
+}
+
+/* match rpmsg channel and rpmsg driver */
+static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
+	const struct rpmsg_device_id *ids = rpdrv->id_table;
+	unsigned int i;
+
+	for (i = 0; ids[i].name[0]; i++)
+		if (rpmsg_id_match(rpdev, &ids[i]))
+			return 1;
+
+	return 0;
+}
+
+static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+
+	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
+					rpdev->id.name);
+}
+
+/* for more info, see below documentation of rpmsg_create_ept() */
+static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
+		struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb,
+		void *priv, u32 addr)
+{
+	int err, tmpaddr, request;
+	struct rpmsg_endpoint *ept;
+	struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev;
+
+	if (!idr_pre_get(&vrp->endpoints, GFP_KERNEL))
+		return NULL;
+
+	ept = kzalloc(sizeof(*ept), GFP_KERNEL);
+	if (!ept) {
+		dev_err(dev, "failed to kzalloc a new ept\n");
+		return NULL;
+	}
+
+	ept->rpdev = rpdev;
+	ept->cb = cb;
+	ept->priv = priv;
+
+	/* do we need to allocate a local address ? */
+	request = addr == RPMSG_ADDR_ANY ? RPMSG_RESERVED_ADDRESSES : addr;
+
+	mutex_lock(&vrp->endpoints_lock);
+
+	/* bind the endpoint to an rpmsg address (and allocate one if needed) */
+	err = idr_get_new_above(&vrp->endpoints, ept, request, &tmpaddr);
+	if (err) {
+		dev_err(dev, "idr_get_new_above failed: %d\n", err);
+		goto free_ept;
+	}
+
+	/* make sure the user's address request is fulfilled, if relevant */
+	if (addr != RPMSG_ADDR_ANY && tmpaddr != addr) {
+		dev_err(dev, "address 0x%x already in use\n", addr);
+		goto rem_idr;
+	}
+
+	ept->addr = tmpaddr;
+
+	mutex_unlock(&vrp->endpoints_lock);
+
+	return ept;
+
+rem_idr:
+	idr_remove(&vrp->endpoints, request);
+free_ept:
+	mutex_unlock(&vrp->endpoints_lock);
+	kfree(ept);
+	return NULL;
+}
+
+/**
+ * rpmsg_create_ept() - create a new rpmsg_endpoint
+ * @rpdev: rpmsg channel device
+ * @cb: rx callback handler
+ * @priv: private data for the driver's use
+ * @addr: local rpmsg address to bind with @cb
+ *
+ * Every rpmsg address in the system is bound to an rx callback (so when
+ * inbound messages arrive, they are dispatched by the rpmsg bus using the
+ * appropriate callback handler) by means of an rpmsg_endpoint struct.
+ *
+ * This function allows drivers to create such an endpoint, and by that,
+ * bind a callback, and possibly some private data too, to an rpmsg address
+ * (either one that is known in advance, or one that will be dynamically
+ * assigned for them).
+ *
+ * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
+ * is already created for them when they are probed by the rpmsg bus
+ * (using the rx callback provided when they registered to the rpmsg bus).
+ *
+ * So things should just work for simple drivers: they already have an
+ * endpoint, their rx callback is bound to their rpmsg address, and when
+ * relevant inbound messages arrive (i.e. messages which their dst address
+ * equals to the src address of their rpmsg channel), the driver's handler
+ * is invoked to process it.
+ *
+ * That said, more complicated drivers might do need to allocate
+ * additional rpmsg addresses, and bind them to different rx callbacks.
+ * To accomplish that, those drivers need to call this function.
+ *
+ * Drivers should provide their @rpdev channel (so the new endpoint would belong
+ * to the same remote processor their channel belongs to), an rx callback
+ * function, an optional private data (which is provided back when the
+ * rx callback is invoked), and an address they want to bind with the
+ * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
+ * dynamically assign them an available rpmsg address (drivers should have
+ * a very good reason why not to always use RPMSG_ADDR_ANY here).
+ *
+ * Returns a pointer to the endpoint on success, or NULL on error.
+ */
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
+				rpmsg_rx_cb_t cb, void *priv, u32 addr)
+{
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+}
+EXPORT_SYMBOL(rpmsg_create_ept);
+
+/**
+ * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
+ * @ept: endpoing to destroy
+ *
+ * Should be used by drivers to destroy an rpmsg endpoint previously
+ * created with rpmsg_create_ept().
+ */
+void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	struct virtproc_info *vrp = ept->rpdev->vrp;
+
+	mutex_lock(&vrp->endpoints_lock);
+	idr_remove(&vrp->endpoints, ept->addr);
+	mutex_unlock(&vrp->endpoints_lock);
+
+	kfree(ept);
+}
+EXPORT_SYMBOL(rpmsg_destroy_ept);
+
+/*
+ * when an rpmsg driver is probed with a channel, we seamlessly create
+ * it an endpoint, binding its rx callback to a unique local rpmsg
+ * address.
+ *
+ * if we need to, we also announce about this channel to the remote
+ * processor (needed in case the driver is exposing an rpmsg service).
+ */
+static int rpmsg_dev_probe(struct device *dev)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct virtproc_info *vrp = rpdev->vrp;
+	struct rpmsg_endpoint *ept;
+	int err;
+
+	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
+	if (!ept) {
+		dev_err(dev, "failed to create endpoint\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rpdev->ept = ept;
+	rpdev->src = ept->addr;
+
+	err = rpdrv->probe(rpdev);
+	if (err) {
+		dev_err(dev, "%s: failed: %d\n", __func__, err);
+		rpmsg_destroy_ept(ept);
+		goto out;
+	}
+
+	/* need to tell remote processor's name service about this channel ? */
+	if (rpdev->announce &&
+			virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
+		struct rpmsg_ns_msg nsm;
+
+		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
+		nsm.addr = rpdev->src;
+		nsm.flags = RPMSG_NS_CREATE;
+
+		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		if (err)
+			dev_err(dev, "failed to announce service %d\n", err);
+	}
+
+out:
+	return err;
+}
+
+static int rpmsg_dev_remove(struct device *dev)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct virtproc_info *vrp = rpdev->vrp;
+	int err = 0;
+
+	/* tell remote processor's name service we're removing this channel */
+	if (rpdev->announce &&
+			virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
+		struct rpmsg_ns_msg nsm;
+
+		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
+		nsm.addr = rpdev->src;
+		nsm.flags = RPMSG_NS_DESTROY;
+
+		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		if (err)
+			dev_err(dev, "failed to announce service %d\n", err);
+	}
+
+	rpdrv->remove(rpdev);
+
+	rpmsg_destroy_ept(rpdev->ept);
+
+	return err;
+}
+
+static struct bus_type rpmsg_bus = {
+	.name		= "rpmsg",
+	.match		= rpmsg_dev_match,
+	.dev_attrs	= rpmsg_dev_attrs,
+	.uevent		= rpmsg_uevent,
+	.probe		= rpmsg_dev_probe,
+	.remove		= rpmsg_dev_remove,
+};
+
+/**
+ * register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+int register_rpmsg_driver(struct rpmsg_driver *rpdrv)
+{
+	rpdrv->drv.bus = &rpmsg_bus;
+	return driver_register(&rpdrv->drv);
+}
+EXPORT_SYMBOL(register_rpmsg_driver);
+
+/**
+ * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
+{
+	driver_unregister(&rpdrv->drv);
+}
+EXPORT_SYMBOL(unregister_rpmsg_driver);
+
+static void rpmsg_release_device(struct device *dev)
+{
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+
+	kfree(rpdev);
+}
+
+/*
+ * match an rpmsg channel with a channel info struct.
+ * this is used to make sure we're not creating rpmsg devices for channels
+ * that already exist.
+ */
+static int rpmsg_channel_match(struct device *dev, void *data)
+{
+	struct rpmsg_channel_info *chinfo = data;
+	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+
+	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
+		return 0;
+
+	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
+		return 0;
+
+	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
+		return 0;
+
+	/* found a match ! */
+	return 1;
+}
+
+/*
+ * create an rpmsg channel using its name and address info.
+ * this function will be used to create both static and dynamic
+ * channels.
+ */
+static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp,
+				struct rpmsg_channel_info *chinfo)
+{
+	struct rpmsg_channel *rpdev;
+	struct device *tmp, *dev = &vrp->vdev->dev;
+	int ret;
+
+	/* make sure a similar channel doesn't already exist */
+	tmp = device_find_child(dev, chinfo, rpmsg_channel_match);
+	if (tmp) {
+		/* decrement the matched device's refcount back */
+		put_device(tmp);
+		dev_err(dev, "channel %s:%x:%x already exist\n",
+				chinfo->name, chinfo->src, chinfo->dst);
+		return NULL;
+	}
+
+	rpdev = kzalloc(sizeof(struct rpmsg_channel), GFP_KERNEL);
+	if (!rpdev) {
+		pr_err("kzalloc failed\n");
+		return NULL;
+	}
+
+	rpdev->vrp = vrp;
+	rpdev->src = chinfo->src;
+	rpdev->dst = chinfo->dst;
+
+	/*
+	 * rpmsg server channels has predefined local address (for now),
+	 * and their existence needs to be announced remotely
+	 */
+	rpdev->announce = rpdev->src != RPMSG_ADDR_ANY ? true : false;
+
+	strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
+
+	/* very simple device indexing plumbing which is enough for now */
+	dev_set_name(&rpdev->dev, "rpmsg%d", rpmsg_dev_index++);
+
+	rpdev->dev.parent = &vrp->vdev->dev;
+	rpdev->dev.bus = &rpmsg_bus;
+	rpdev->dev.release = rpmsg_release_device;
+
+	ret = device_register(&rpdev->dev);
+	if (ret) {
+		dev_err(dev, "device_register failed: %d\n", ret);
+		put_device(&rpdev->dev);
+		return NULL;
+	}
+
+	return rpdev;
+}
+
+/*
+ * find an existing channel using its name + address properties,
+ * and destroy it
+ */
+static int rpmsg_destroy_channel(struct virtproc_info *vrp,
+					struct rpmsg_channel_info *chinfo)
+{
+	struct virtio_device *vdev = vrp->vdev;
+	struct device *dev;
+
+	dev = device_find_child(&vdev->dev, chinfo, rpmsg_channel_match);
+	if (!dev)
+		return -EINVAL;
+
+	device_unregister(dev);
+
+	put_device(dev);
+
+	return 0;
+}
+
+/* super simple buffer "allocator" that is just enough for now */
+static void *get_a_tx_buf(struct virtproc_info *vrp)
+{
+	unsigned int len;
+	void *ret;
+
+	/* support multiple concurrent senders */
+	mutex_lock(&vrp->tx_lock);
+
+	/*
+	 * either pick the next unused tx buffer
+	 * (half of our buffers are used for sending messages)
+	 */
+	if (vrp->last_sbuf < RPMSG_NUM_BUFS / 2)
+		ret = vrp->sbufs + RPMSG_BUF_SIZE * vrp->last_sbuf++;
+	/* or recycle a used one */
+	else
+		ret = virtqueue_get_buf(vrp->svq, &len);
+
+	mutex_unlock(&vrp->tx_lock);
+
+	return ret;
+}
+
+/**
+ * rpmsg_upref_sleepers() - enable "tx-complete" interrupts, if needed
+ * @vrp: virtual remote processor state
+ *
+ * This function is called before a sender is blocked, waiting for
+ * a tx buffer to become available.
+ *
+ * If we already have blocking senders, this function merely increases
+ * the "sleepers" reference count, and exits.
+ *
+ * Otherwise, if this is the first sender to block, we also enable
+ * virtio's tx callbacks, so we'd be immediately notified when a tx
+ * buffer is consumed (we rely on virtio's tx callback in order
+ * to wake up sleeping senders as soon as a tx buffer is used by the
+ * remote processor).
+ */
+static void rpmsg_upref_sleepers(struct virtproc_info *vrp)
+{
+	/* support multiple concurrent senders */
+	mutex_lock(&vrp->tx_lock);
+
+	/* are we the first sleeping context waiting for tx buffers ? */
+	if (atomic_inc_return(&vrp->sleepers) == 1)
+		/* enable "tx-complete" interrupts before dozing off */
+		virtqueue_enable_cb(vrp->svq);
+
+	mutex_unlock(&vrp->tx_lock);
+}
+
+/**
+ * rpmsg_downref_sleepers() - disable "tx-complete" interrupts, if needed
+ * @vrp: virtual remote processor state
+ *
+ * This function is called after a sender, that waited for a tx buffer
+ * to become available, is unblocked.
+ *
+ * If we still have blocking senders, this function merely decreases
+ * the "sleepers" reference count, and exits.
+ *
+ * Otherwise, if there are no more blocking senders, we also disable
+ * virtio's tx callbacks, to avoid the overhead incurred with handling
+ * those (now redundant) interrupts.
+ */
+static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
+{
+	/* support multiple concurrent senders */
+	mutex_lock(&vrp->tx_lock);
+
+	/* are we the last sleeping context waiting for tx buffers ? */
+	if (atomic_dec_and_test(&vrp->sleepers))
+		/* disable "tx-complete" interrupts */
+		virtqueue_disable_cb(vrp->svq);
+
+	mutex_unlock(&vrp->tx_lock);
+}
+
+/**
+ * rpmsg_send_offchannel_raw() - send a message across to the remote processor
+ * @rpdev: the rpmsg channel
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ * @wait: indicates whether caller should block in case no TX buffers available
+ *
+ * This function is the base implementation for all of the rpmsg sending API.
+ *
+ * It will send @data of length @len to @dst, and say it's from @src. The
+ * message will be sent to the remote processor which the @rpdev channel
+ * belongs to.
+ *
+ * The message is sent using one of the TX buffers that are available for
+ * communication with this remote processor.
+ *
+ * If @wait is true, the caller will be blocked until either a TX buffer is
+ * available, or 15 seconds elapses (we don't want callers to
+ * sleep indefinitely due to misbehaving remote processors), and in that
+ * case -ERESTARTSYS is returned. The number '15' itself was picked
+ * arbitrarily; there's little point in asking drivers to provide a timeout
+ * value themselves.
+ *
+ * Otherwise, if @wait is false, and there are no TX buffers available,
+ * the function will immediately fail, and -ENOMEM will be returned.
+ *
+ * Normally drivers shouldn't use this function directly; instead, drivers
+ * should use the appropriate rpmsg_{try}send{to, _offchannel} API
+ * (see include/linux/rpmsg.h).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+					void *data, int len, bool wait)
+{
+	struct virtproc_info *vrp = rpdev->vrp;
+	struct device *dev = &rpdev->dev;
+	struct scatterlist sg;
+	struct rpmsg_hdr *msg;
+	int err;
+
+	/* bcasting isn't allowed */
+	if (src == RPMSG_ADDR_ANY || dst == RPMSG_ADDR_ANY) {
+		dev_err(dev, "invalid addr (src 0x%x, dst 0x%x)\n", src, dst);
+		return -EINVAL;
+	}
+
+	/*
+	 * We currently use fixed-sized buffers, and therefore the payload
+	 * length is limited.
+	 *
+	 * One of the possible improvements here is either to support
+	 * user-provided buffers (and then we can also support zero-copy
+	 * messaging), or to improve the buffer allocator, to support
+	 * variable-length buffer sizes.
+	 */
+	if (len > RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) {
+		dev_err(dev, "message is too big (%d)\n", len);
+		return -EMSGSIZE;
+	}
+
+	/* grab a buffer */
+	msg = get_a_tx_buf(vrp);
+	if (!msg && !wait)
+		return -ENOMEM;
+
+	/* no free buffer ? wait for one (but bail after 15 seconds) */
+	while (!msg) {
+		/* enable "tx-complete" interrupts, if not already enabled */
+		rpmsg_upref_sleepers(vrp);
+
+		/*
+		 * sleep until a free buffer is available or 15 secs elapse.
+		 * the timeout period is not configurable because there's
+		 * little point in asking drivers to specify that.
+		 * if later this happens to be required, it'd be easy to add.
+		 */
+		err = wait_event_interruptible_timeout(vrp->sendq,
+					(msg = get_a_tx_buf(vrp)),
+					msecs_to_jiffies(15000));
+
+		/* disable "tx-complete" interrupts if we're the last sleeper */
+		rpmsg_downref_sleepers(vrp);
+
+		/* timeout ? */
+		if (!err) {
+			dev_err(dev, "timeout waiting for a tx buffer\n");
+			return -ERESTARTSYS;
+		}
+	}
+
+	msg->len = len;
+	msg->flags = 0;
+	msg->src = src;
+	msg->dst = dst;
+	msg->reserved = 0;
+	memcpy(msg->data, data, len);
+
+	dev_dbg(dev, "TX From 0x%x, To 0x%x, Len %d, Flags %d, Reserved %d\n",
+					msg->src, msg->dst, msg->len,
+					msg->flags, msg->reserved);
+	print_hex_dump(KERN_DEBUG, "rpmsg_virtio TX: ", DUMP_PREFIX_NONE, 16, 1,
+					msg, sizeof(*msg) + msg->len, true);
+
+	sg_init_one(&sg, msg, sizeof(*msg) + len);
+
+	mutex_lock(&vrp->tx_lock);
+
+	/* add message to the remote processor's virtqueue */
+	err = virtqueue_add_buf(vrp->svq, &sg, 1, 0, msg, GFP_KERNEL);
+	if (err < 0) {
+		/*
+		 * need to reclaim the buffer here, otherwise it's lost
+		 * (memory won't leak, but rpmsg won't use it again for TX).
+		 * this will wait for a buffer management overhaul.
+		 */
+		dev_err(dev, "virtqueue_add_buf failed: %d\n", err);
+		goto out;
+	}
+
+	/* tell the remote processor it has a pending message to read */
+	virtqueue_kick(vrp->svq);
+
+	err = 0;
+out:
+	mutex_unlock(&vrp->tx_lock);
+	return err;
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
+
+/* called when an rx buffer is used, and it's time to digest a message */
+static void rpmsg_recv_done(struct virtqueue *rvq)
+{
+	struct rpmsg_hdr *msg;
+	unsigned int len;
+	struct rpmsg_endpoint *ept;
+	struct scatterlist sg;
+	struct virtproc_info *vrp = rvq->vdev->priv;
+	struct device *dev = &rvq->vdev->dev;
+	int err;
+
+	msg = virtqueue_get_buf(rvq, &len);
+	if (!msg) {
+		dev_err(dev, "uhm, incoming signal, but no used buffer ?\n");
+		return;
+	}
+
+	dev_dbg(dev, "From: 0x%x, To: 0x%x, Len: %d, Flags: %d, Reserved: %d\n",
+					msg->src, msg->dst, msg->len,
+					msg->flags, msg->reserved);
+	print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1,
+					msg, sizeof(*msg) + msg->len, true);
+
+	/* use the dst addr to fetch the callback of the appropriate user */
+	mutex_lock(&vrp->endpoints_lock);
+	ept = idr_find(&vrp->endpoints, msg->dst);
+	mutex_unlock(&vrp->endpoints_lock);
+
+	if (ept && ept->cb)
+		ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src);
+	else
+		dev_warn(dev, "msg received with no recepient\n");
+
+	sg_init_one(&sg, msg, sizeof(*msg) + len);
+
+	/* add the buffer back to the remote processor's virtqueue */
+	err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL);
+	if (err < 0) {
+		dev_err(dev, "failed to add a virtqueue buffer: %d\n", err);
+		return;
+	}
+
+	/* tell the remote processor we added another available rx buffer */
+	virtqueue_kick(vrp->rvq);
+}
+
+/*
+ * This is invoked whenever the remote processor completed processing
+ * a TX msg we just sent it, and the buffer is put back to the used ring.
+ *
+ * Normally, though, we suppress this "tx complete" interrupt in order to
+ * avoid the incurred overhead.
+ */
+static void rpmsg_xmit_done(struct virtqueue *svq)
+{
+	struct virtproc_info *vrp = svq->vdev->priv;
+
+	dev_dbg(&svq->vdev->dev, "%s\n", __func__);
+
+	/* wake up potential senders that are waiting for a tx buffer */
+	wake_up_interruptible(&vrp->sendq);
+}
+
+/* invoked when a name service announcement arrives */
+static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len,
+							void *priv, u32 src)
+{
+	struct rpmsg_ns_msg *msg = data;
+	struct rpmsg_channel *newch;
+	struct rpmsg_channel_info chinfo;
+	struct virtproc_info *vrp = priv;
+	struct device *dev = &vrp->vdev->dev;
+	int ret;
+
+	print_hex_dump(KERN_DEBUG, "NS announcement: ",
+			DUMP_PREFIX_NONE, 16, 1,
+			data, len, true);
+
+	if (len != sizeof(*msg)) {
+		dev_err(dev, "malformed ns msg (%d)\n", len);
+		return;
+	}
+
+	/*
+	 * the name service ept does _not_ belong to a real rpmsg channel,
+	 * and is handled by the rpmsg bus itself.
+	 * for sanity reasons, make sure a valid rpdev has _not_ sneaked
+	 * in somehow.
+	 */
+	if (rpdev) {
+		dev_err(dev, "anomaly: ns ept has an rpdev handle\n");
+		return;
+	}
+
+	/* don't trust the remote processor for null terminating the name */
+	msg->name[RPMSG_NAME_SIZE - 1] = '\0';
+
+	dev_info(dev, "%sing channel %s addr 0x%x\n",
+			msg->flags & RPMSG_NS_DESTROY ? "destroy" : "creat",
+			msg->name, msg->addr);
+
+	strncpy(chinfo.name, msg->name, sizeof(chinfo.name));
+	chinfo.src = RPMSG_ADDR_ANY;
+	chinfo.dst = msg->addr;
+
+	if (msg->flags & RPMSG_NS_DESTROY) {
+		ret = rpmsg_destroy_channel(vrp, &chinfo);
+		if (ret)
+			dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
+	} else {
+		newch = rpmsg_create_channel(vrp, &chinfo);
+		if (!newch)
+			dev_err(dev, "rpmsg_create_channel failed\n");
+	}
+}
+
+static int rpmsg_probe(struct virtio_device *vdev)
+{
+	vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done };
+	const char *names[] = { "input", "output" };
+	struct virtqueue *vqs[2];
+	struct virtproc_info *vrp;
+	void *bufs_va;
+	int err = 0, i;
+
+	vrp = kzalloc(sizeof(*vrp), GFP_KERNEL);
+	if (!vrp)
+		return -ENOMEM;
+
+	vrp->vdev = vdev;
+
+	idr_init(&vrp->endpoints);
+	mutex_init(&vrp->endpoints_lock);
+	mutex_init(&vrp->tx_lock);
+	init_waitqueue_head(&vrp->sendq);
+
+	/* We expect two virtqueues, rx and tx (and in this order) */
+	err = vdev->config->find_vqs(vdev, 2, vqs, vq_cbs, names);
+	if (err)
+		goto free_vrp;
+
+	vrp->rvq = vqs[0];
+	vrp->svq = vqs[1];
+
+	/* allocate coherent memory for the buffers */
+	bufs_va = dma_alloc_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE,
+				&vrp->bufs_dma, GFP_KERNEL);
+	if (!bufs_va)
+		goto vqs_del;
+
+	dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%x\n", bufs_va,
+						vrp->bufs_dma);
+
+	/* half of the buffers is dedicated for RX */
+	vrp->rbufs = bufs_va;
+
+	/* and half is dedicated for TX */
+	vrp->sbufs = bufs_va + RPMSG_TOTAL_BUF_SPACE / 2;
+
+	/* set up the receive buffers */
+	for (i = 0; i < RPMSG_NUM_BUFS / 2; i++) {
+		struct scatterlist sg;
+		void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE;
+
+		sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
+
+		err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr,
+								GFP_KERNEL);
+		WARN_ON(err < 0); /* sanity check; this can't really happen */
+	}
+
+	/* suppress "tx-complete" interrupts */
+	virtqueue_disable_cb(vrp->svq);
+
+	vdev->priv = vrp;
+
+	/* if supported by the remote processor, enable the name service */
+	if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) {
+		/* a dedicated endpoint handles the name service msgs */
+		vrp->ns_ept = __rpmsg_create_ept(vrp, NULL, rpmsg_ns_cb,
+						vrp, RPMSG_NS_ADDR);
+		if (!vrp->ns_ept) {
+			dev_err(&vdev->dev, "failed to create the ns ept\n");
+			err = -ENOMEM;
+			goto free_coherent;
+		}
+	}
+
+	/* tell the remote processor it can start sending messages */
+	virtqueue_kick(vrp->rvq);
+
+	dev_info(&vdev->dev, "rpmsg host is online\n");
+
+	return 0;
+
+free_coherent:
+	dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va,
+					vrp->bufs_dma);
+vqs_del:
+	vdev->config->del_vqs(vrp->vdev);
+free_vrp:
+	kfree(vrp);
+	return err;
+}
+
+static int rpmsg_remove_device(struct device *dev, void *data)
+{
+	device_unregister(dev);
+
+	return 0;
+}
+
+static void __devexit rpmsg_remove(struct virtio_device *vdev)
+{
+	struct virtproc_info *vrp = vdev->priv;
+	int ret;
+
+	vdev->config->reset(vdev);
+
+	ret = device_for_each_child(&vdev->dev, NULL, rpmsg_remove_device);
+	if (ret)
+		dev_warn(&vdev->dev, "can't remove rpmsg device: %d\n", ret);
+
+	idr_remove_all(&vrp->endpoints);
+	idr_destroy(&vrp->endpoints);
+
+	vdev->config->del_vqs(vrp->vdev);
+
+	dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE,
+					vrp->rbufs, vrp->bufs_dma);
+
+	kfree(vrp);
+}
+
+static struct virtio_device_id id_table[] = {
+	{ VIRTIO_ID_RPMSG, VIRTIO_DEV_ANY_ID },
+	{ 0 },
+};
+
+static unsigned int features[] = {
+	VIRTIO_RPMSG_F_NS,
+};
+
+static struct virtio_driver virtio_ipc_driver = {
+	.feature_table	= features,
+	.feature_table_size = ARRAY_SIZE(features),
+	.driver.name	= KBUILD_MODNAME,
+	.driver.owner	= THIS_MODULE,
+	.id_table	= id_table,
+	.probe		= rpmsg_probe,
+	.remove		= __devexit_p(rpmsg_remove),
+};
+
+static int __init rpmsg_init(void)
+{
+	int ret;
+
+	ret = bus_register(&rpmsg_bus);
+	if (ret) {
+		pr_err("failed to register rpmsg bus: %d\n", ret);
+		return ret;
+	}
+
+	ret = register_virtio_driver(&virtio_ipc_driver);
+	if (ret) {
+		pr_err("failed to register virtio driver: %d\n", ret);
+		bus_unregister(&rpmsg_bus);
+	}
+
+	return ret;
+}
+module_init(rpmsg_init);
+
+static void __exit rpmsg_fini(void)
+{
+	unregister_virtio_driver(&virtio_ipc_driver);
+	bus_unregister(&rpmsg_bus);
+}
+module_exit(rpmsg_fini);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio-based remote processor messaging bus");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e19a403..3a125b8 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -774,7 +774,7 @@ config RTC_DRV_EP93XX
 
 config RTC_DRV_SA1100
 	tristate "SA11x0/PXA2xx"
-	depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+	depends on ARCH_SA1100 || ARCH_PXA
 	help
 	  If you say Y here you will get access to the real time clock
 	  built into your SA11x0 or PXA2xx CPU.
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index aef40bd..7895186 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -35,6 +35,8 @@
 
 enum s3c_cpu_type {
 	TYPE_S3C2410,
+	TYPE_S3C2416,
+	TYPE_S3C2443,
 	TYPE_S3C64XX,
 };
 
@@ -132,6 +134,7 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
 	unsigned int tmp = 0;
+	int val;
 
 	if (!is_power_of_2(freq))
 		return -EINVAL;
@@ -139,12 +142,22 @@ static int s3c_rtc_setfreq(struct device *dev, int freq)
 	clk_enable(rtc_clk);
 	spin_lock_irq(&s3c_rtc_pie_lock);
 
-	if (s3c_rtc_cpu_type == TYPE_S3C2410) {
+	if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
 		tmp = readb(s3c_rtc_base + S3C2410_TICNT);
 		tmp &= S3C2410_TICNT_ENABLE;
 	}
 
-	tmp |= (rtc_dev->max_user_freq / freq)-1;
+	val = (rtc_dev->max_user_freq / freq) - 1;
+
+	if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
+		tmp |= S3C2443_TICNT_PART(val);
+		writel(S3C2443_TICNT1_PART(val), s3c_rtc_base + S3C2443_TICNT1);
+
+		if (s3c_rtc_cpu_type == TYPE_S3C2416)
+			writel(S3C2416_TICNT2_PART(val), s3c_rtc_base + S3C2416_TICNT2);
+	} else {
+		tmp |= val;
+	}
 
 	writel(tmp, s3c_rtc_base + S3C2410_TICNT);
 	spin_unlock_irq(&s3c_rtc_pie_lock);
@@ -371,7 +384,7 @@ static void s3c_rtc_enable(struct platform_device *pdev, int en)
 		tmp &= ~S3C2410_RTCCON_RTCEN;
 		writew(tmp, base + S3C2410_RTCCON);
 
-		if (s3c_rtc_cpu_type == TYPE_S3C2410) {
+		if (s3c_rtc_cpu_type != TYPE_S3C64XX) {
 			tmp = readb(base + S3C2410_TICNT);
 			tmp &= ~S3C2410_TICNT_ENABLE;
 			writeb(tmp, base + S3C2410_TICNT);
@@ -428,12 +441,27 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
 	return 0;
 }
 
+static const struct of_device_id s3c_rtc_dt_match[];
+
+static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
+		return match->data;
+	}
+#endif
+	return platform_get_device_id(pdev)->driver_data;
+}
+
 static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 	struct rtc_time rtc_tm;
 	struct resource *res;
 	int ret;
+	int tmp;
 
 	pr_debug("%s: probe=%p\n", __func__, pdev);
 
@@ -508,13 +536,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 		goto err_nortc;
 	}
 
-#ifdef CONFIG_OF
-	if (pdev->dev.of_node)
-		s3c_rtc_cpu_type = of_device_is_compatible(pdev->dev.of_node,
-			"samsung,s3c6410-rtc") ? TYPE_S3C64XX : TYPE_S3C2410;
-	else
-#endif
-		s3c_rtc_cpu_type = platform_get_device_id(pdev)->driver_data;
+	s3c_rtc_cpu_type = s3c_rtc_get_driver_data(pdev);
 
 	/* Check RTC Time */
 
@@ -533,11 +555,17 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev)
 		dev_warn(&pdev->dev, "warning: invalid RTC value so initializing it\n");
 	}
 
-	if (s3c_rtc_cpu_type == TYPE_S3C64XX)
+	if (s3c_rtc_cpu_type != TYPE_S3C2410)
 		rtc->max_user_freq = 32768;
 	else
 		rtc->max_user_freq = 128;
 
+	if (s3c_rtc_cpu_type == TYPE_S3C2416 || s3c_rtc_cpu_type == TYPE_S3C2443) {
+		tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
+		tmp |= S3C2443_RTCCON_TICSEL;
+		writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
+	}
+
 	platform_set_drvdata(pdev, rtc);
 
 	s3c_rtc_setfreq(&pdev->dev, 1);
@@ -638,8 +666,19 @@ static int s3c_rtc_resume(struct platform_device *pdev)
 
 #ifdef CONFIG_OF
 static const struct of_device_id s3c_rtc_dt_match[] = {
-	{ .compatible = "samsung,s3c2410-rtc" },
-	{ .compatible = "samsung,s3c6410-rtc" },
+	{
+		.compatible = "samsung,s3c2410-rtc"
+		.data = TYPE_S3C2410,
+	}, {
+		.compatible = "samsung,s3c2416-rtc"
+		.data = TYPE_S3C2416,
+	}, {
+		.compatible = "samsung,s3c2443-rtc"
+		.data = TYPE_S3C2443,
+	}, {
+		.compatible = "samsung,s3c6410-rtc"
+		.data = TYPE_S3C64XX,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
@@ -652,6 +691,12 @@ static struct platform_device_id s3c_rtc_driver_ids[] = {
 		.name		= "s3c2410-rtc",
 		.driver_data	= TYPE_S3C2410,
 	}, {
+		.name		= "s3c2416-rtc",
+		.driver_data	= TYPE_S3C2416,
+	}, {
+		.name		= "s3c2443-rtc",
+		.driver_data	= TYPE_S3C2443,
+	}, {
 		.name		= "s3c64xx-rtc",
 		.driver_data	= TYPE_S3C64XX,
 	},
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 4595d3e..cb9a585 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -27,42 +27,34 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/interrupt.h>
+#include <linux/string.h>
 #include <linux/pm.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <mach/regs-rtc.h>
+#endif
+
 #define RTC_DEF_DIVIDER		(32768 - 1)
 #define RTC_DEF_TRIM		0
-#define RTC_FREQ		1024
-
-#define RCNR		0x00	/* RTC Count Register */
-#define RTAR		0x04	/* RTC Alarm Register */
-#define RTSR		0x08	/* RTC Status Register */
-#define RTTR		0x0c	/* RTC Timer Trim Register */
-
-#define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
-#define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
-#define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
-#define RTSR_AL		(1 << 0)	/* RTC alarm detected */
-
-#define rtc_readl(sa1100_rtc, reg)	\
-	readl_relaxed((sa1100_rtc)->base + (reg))
-#define rtc_writel(sa1100_rtc, reg, value)	\
-	writel_relaxed((value), (sa1100_rtc)->base + (reg))
-
-struct sa1100_rtc {
-	struct resource		*ress;
-	void __iomem		*base;
-	struct clk		*clk;
-	int			irq_1Hz;
-	int			irq_Alrm;
-	struct rtc_device	*rtc;
-	spinlock_t		lock;		/* Protects this structure */
-};
+
+static const unsigned long RTC_FREQ = 1024;
+static struct rtc_time rtc_alarm;
+static DEFINE_SPINLOCK(sa1100_rtc_lock);
+
+static inline int rtc_periodic_alarm(struct rtc_time *tm)
+{
+	return  (tm->tm_year == -1) ||
+		((unsigned)tm->tm_mon >= 12) ||
+		((unsigned)(tm->tm_mday - 1) >= 31) ||
+		((unsigned)tm->tm_hour > 23) ||
+		((unsigned)tm->tm_min > 59) ||
+		((unsigned)tm->tm_sec > 59);
+}
+
 /*
  * Calculate the next alarm time given the requested alarm time mask
  * and the current time.
@@ -90,26 +82,46 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
 	}
 }
 
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+	struct rtc_time alarm_tm, now_tm;
+	unsigned long now, time;
+	int ret;
+
+	do {
+		now = RCNR;
+		rtc_time_to_tm(now, &now_tm);
+		rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+		ret = rtc_tm_to_time(&alarm_tm, &time);
+		if (ret != 0)
+			break;
+
+		RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+		RTAR = time;
+	} while (now != RCNR);
+
+	return ret;
+}
+
 static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 {
 	struct platform_device *pdev = to_platform_device(dev_id);
-	struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
 	unsigned int rtsr;
 	unsigned long events = 0;
 
-	spin_lock(&sa1100_rtc->lock);
+	spin_lock(&sa1100_rtc_lock);
 
+	rtsr = RTSR;
 	/* clear interrupt sources */
-	rtsr = rtc_readl(sa1100_rtc, RTSR);
-	rtc_writel(sa1100_rtc, RTSR, 0);
-
+	RTSR = 0;
 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
 	 * See also the comments in sa1100_rtc_probe(). */
 	if (rtsr & (RTSR_ALE | RTSR_HZE)) {
 		/* This is the original code, before there was the if test
 		 * above. This code does not clear interrupts that were not
 		 * enabled. */
-		rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2));
+		RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
 	} else {
 		/* For some reason, it is possible to enter this routine
 		 * without interruptions enabled, it has been tested with
@@ -118,13 +130,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 		 * This situation leads to an infinite "loop" of interrupt
 		 * routine calling and as a result the processor seems to
 		 * lock on its first call to open(). */
-		rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+		RTSR = RTSR_AL | RTSR_HZ;
 	}
 
 	/* clear alarm interrupt if it has occurred */
 	if (rtsr & RTSR_AL)
 		rtsr &= ~RTSR_ALE;
-	rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE));
+	RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
 
 	/* update irq data & counter */
 	if (rtsr & RTSR_AL)
@@ -132,100 +144,89 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 	if (rtsr & RTSR_HZ)
 		events |= RTC_UF | RTC_IRQF;
 
-	rtc_update_irq(sa1100_rtc->rtc, 1, events);
+	rtc_update_irq(rtc, 1, events);
 
-	spin_unlock(&sa1100_rtc->lock);
+	if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+		rtc_update_alarm(&rtc_alarm);
+
+	spin_unlock(&sa1100_rtc_lock);
 
 	return IRQ_HANDLED;
 }
 
 static int sa1100_rtc_open(struct device *dev)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
 	int ret;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
-	ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt,
-				IRQF_DISABLED, "rtc 1Hz", dev);
+	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
+		"rtc 1Hz", dev);
 	if (ret) {
-		dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
 		goto fail_ui;
 	}
-	ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt,
-				IRQF_DISABLED, "rtc Alrm", dev);
+	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
+		"rtc Alrm", dev);
 	if (ret) {
-		dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm);
+		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
-	sa1100_rtc->rtc->max_user_freq = RTC_FREQ;
-	rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ);
+	rtc->max_user_freq = RTC_FREQ;
+	rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
 	return 0;
 
  fail_ai:
-	free_irq(sa1100_rtc->irq_1Hz, dev);
+	free_irq(IRQ_RTC1Hz, dev);
  fail_ui:
 	return ret;
 }
 
 static void sa1100_rtc_release(struct device *dev)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
-	spin_lock_irq(&sa1100_rtc->lock);
-	rtc_writel(sa1100_rtc, RTSR, 0);
-	spin_unlock_irq(&sa1100_rtc->lock);
+	spin_lock_irq(&sa1100_rtc_lock);
+	RTSR = 0;
+	spin_unlock_irq(&sa1100_rtc_lock);
 
-	free_irq(sa1100_rtc->irq_Alrm, dev);
-	free_irq(sa1100_rtc->irq_1Hz, dev);
+	free_irq(IRQ_RTCAlrm, dev);
+	free_irq(IRQ_RTC1Hz, dev);
 }
 
 static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-	unsigned int rtsr;
-
-	spin_lock_irq(&sa1100_rtc->lock);
-
-	rtsr = rtc_readl(sa1100_rtc, RTSR);
+	spin_lock_irq(&sa1100_rtc_lock);
 	if (enabled)
-		rtsr |= RTSR_ALE;
+		RTSR |= RTSR_ALE;
 	else
-		rtsr &= ~RTSR_ALE;
-	rtc_writel(sa1100_rtc, RTSR, rtsr);
-
-	spin_unlock_irq(&sa1100_rtc->lock);
+		RTSR &= ~RTSR_ALE;
+	spin_unlock_irq(&sa1100_rtc_lock);
 	return 0;
 }
 
 static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
-	rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm);
+	rtc_time_to_tm(RCNR, tm);
 	return 0;
 }
 
 static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
 	unsigned long time;
 	int ret;
 
 	ret = rtc_tm_to_time(tm, &time);
 	if (ret == 0)
-		rtc_writel(sa1100_rtc, RCNR, time);
+		RCNR = time;
 	return ret;
 }
 
 static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-	unsigned long time;
-	unsigned int rtsr;
+	u32	rtsr;
 
-	time = rtc_readl(sa1100_rtc, RCNR);
-	rtc_time_to_tm(time, &alrm->time);
-	rtsr = rtc_readl(sa1100_rtc, RTSR);
+	memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+	rtsr = RTSR;
 	alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
 	alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
 	return 0;
@@ -233,39 +234,26 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-	struct rtc_time now_tm, alarm_tm;
-	unsigned long time, alarm;
-	unsigned int rtsr;
-
-	spin_lock_irq(&sa1100_rtc->lock);
-
-	time = rtc_readl(sa1100_rtc, RCNR);
-	rtc_time_to_tm(time, &now_tm);
-	rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
-	rtc_tm_to_time(&alarm_tm, &alarm);
-	rtc_writel(sa1100_rtc, RTAR, alarm);
-
-	rtsr = rtc_readl(sa1100_rtc, RTSR);
-	if (alrm->enabled)
-		rtsr |= RTSR_ALE;
-	else
-		rtsr &= ~RTSR_ALE;
-	rtc_writel(sa1100_rtc, RTSR, rtsr);
+	int ret;
 
-	spin_unlock_irq(&sa1100_rtc->lock);
+	spin_lock_irq(&sa1100_rtc_lock);
+	ret = rtc_update_alarm(&alrm->time);
+	if (ret == 0) {
+		if (alrm->enabled)
+			RTSR |= RTSR_ALE;
+		else
+			RTSR &= ~RTSR_ALE;
+	}
+	spin_unlock_irq(&sa1100_rtc_lock);
 
-	return 0;
+	return ret;
 }
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
+	seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+	seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
 
-	seq_printf(seq, "trim/divider\t\t: 0x%08x\n",
-			rtc_readl(sa1100_rtc, RTTR));
-	seq_printf(seq, "RTSR\t\t\t: 0x%08x\n",
-			rtc_readl(sa1100_rtc, RTSR));
 	return 0;
 }
 
@@ -282,51 +270,7 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
 
 static int sa1100_rtc_probe(struct platform_device *pdev)
 {
-	struct sa1100_rtc *sa1100_rtc;
-	unsigned int rttr;
-	int ret;
-
-	sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
-	if (!sa1100_rtc)
-		return -ENOMEM;
-
-	spin_lock_init(&sa1100_rtc->lock);
-	platform_set_drvdata(pdev, sa1100_rtc);
-
-	ret = -ENXIO;
-	sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!sa1100_rtc->ress) {
-		dev_err(&pdev->dev, "No I/O memory resource defined\n");
-		goto err_ress;
-	}
-
-	sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0);
-	if (sa1100_rtc->irq_1Hz < 0) {
-		dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n");
-		goto err_ress;
-	}
-	sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1);
-	if (sa1100_rtc->irq_Alrm < 0) {
-		dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
-		goto err_ress;
-	}
-
-	ret = -ENOMEM;
-	sa1100_rtc->base = ioremap(sa1100_rtc->ress->start,
-				resource_size(sa1100_rtc->ress));
-	if (!sa1100_rtc->base) {
-		dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
-		goto err_map;
-	}
-
-	sa1100_rtc->clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(sa1100_rtc->clk)) {
-		dev_err(&pdev->dev, "failed to find rtc clock source\n");
-		ret = PTR_ERR(sa1100_rtc->clk);
-		goto err_clk;
-	}
-	clk_prepare(sa1100_rtc->clk);
-	clk_enable(sa1100_rtc->clk);
+	struct rtc_device *rtc;
 
 	/*
 	 * According to the manual we should be able to let RTTR be zero
@@ -335,24 +279,24 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
 	 * If the clock divider is uninitialized then reset it to the
 	 * default value to get the 1Hz clock.
 	 */
-	if (rtc_readl(sa1100_rtc, RTTR) == 0) {
-		rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-		rtc_writel(sa1100_rtc, RTTR, rttr);
-		dev_warn(&pdev->dev, "warning: initializing default clock"
-			 " divider/trim value\n");
+	if (RTTR == 0) {
+		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+		dev_warn(&pdev->dev, "warning: "
+			"initializing default clock divider/trim value\n");
 		/* The current RTC value probably doesn't make sense either */
-		rtc_writel(sa1100_rtc, RCNR, 0);
+		RCNR = 0;
 	}
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
-						&sa1100_rtc_ops, THIS_MODULE);
-	if (IS_ERR(sa1100_rtc->rtc)) {
-		dev_err(&pdev->dev, "Failed to register RTC device -> %d\n",
-			ret);
-		goto err_rtc_reg;
-	}
+	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+		THIS_MODULE);
+
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	platform_set_drvdata(pdev, rtc);
+
 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
 	 * See also the comments in sa1100_rtc_interrupt().
 	 *
@@ -375,46 +319,33 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
 	 *
 	 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
 	 * the corresponding bits in RTSR. */
-	rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+	RTSR = RTSR_AL | RTSR_HZ;
 
 	return 0;
-
-err_rtc_reg:
-err_clk:
-	iounmap(sa1100_rtc->base);
-err_ress:
-err_map:
-	kfree(sa1100_rtc);
-	return ret;
 }
 
 static int sa1100_rtc_remove(struct platform_device *pdev)
 {
-	struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	if (rtc)
+		rtc_device_unregister(rtc);
 
-	rtc_device_unregister(sa1100_rtc->rtc);
-	clk_disable(sa1100_rtc->clk);
-	clk_unprepare(sa1100_rtc->clk);
-	iounmap(sa1100_rtc->base);
 	return 0;
 }
 
 #ifdef CONFIG_PM
 static int sa1100_rtc_suspend(struct device *dev)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
 	if (device_may_wakeup(dev))
-		enable_irq_wake(sa1100_rtc->irq_Alrm);
+		enable_irq_wake(IRQ_RTCAlrm);
 	return 0;
 }
 
 static int sa1100_rtc_resume(struct device *dev)
 {
-	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
 	if (device_may_wakeup(dev))
-		disable_irq_wake(sa1100_rtc->irq_Alrm);
+		disable_irq_wake(IRQ_RTCAlrm);
 	return 0;
 }
 
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index 19a28a6..e38da0d 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -77,9 +77,11 @@
 #define STATUS_FAIL		(LOST_WR_TIME | LOST_WR_DATE)
 
 struct spear_rtc_config {
+	struct rtc_device *rtc;
 	struct clk *clk;
 	spinlock_t lock;
 	void __iomem *ioaddr;
+	unsigned int irq_wake;
 };
 
 static inline void spear_rtc_clear_interrupt(struct spear_rtc_config *config)
@@ -149,8 +151,7 @@ static void rtc_wait_not_busy(struct spear_rtc_config *config)
 
 static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
 {
-	struct rtc_device *rtc = (struct rtc_device *)dev_id;
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = dev_id;
 	unsigned long flags, events = 0;
 	unsigned int irq_data;
 
@@ -161,7 +162,7 @@ static irqreturn_t spear_rtc_irq(int irq, void *dev_id)
 	if ((irq_data & RTC_INT_MASK)) {
 		spear_rtc_clear_interrupt(config);
 		events = RTC_IRQF | RTC_AF;
-		rtc_update_irq(rtc, 1, events);
+		rtc_update_irq(config->rtc, 1, events);
 		return IRQ_HANDLED;
 	} else
 		return IRQ_NONE;
@@ -203,9 +204,7 @@ static void bcd2tm(struct rtc_time *tm)
  */
 static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = dev_get_drvdata(dev);
 	unsigned int time, date;
 
 	/* we don't report wday/yday/isdst ... */
@@ -234,9 +233,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm)
  */
 static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = dev_get_drvdata(dev);
 	unsigned int time, date, err = 0;
 
 	if (tm2bcd(tm) < 0)
@@ -266,9 +263,7 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm)
  */
 static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = dev_get_drvdata(dev);
 	unsigned int time, date;
 
 	rtc_wait_not_busy(config);
@@ -298,9 +293,7 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
  */
 static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = dev_get_drvdata(dev);
 	unsigned int time, date, err = 0;
 
 	if (tm2bcd(&alm->time) < 0)
@@ -326,17 +319,42 @@ static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
 	return 0;
 }
+
+static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct spear_rtc_config *config = dev_get_drvdata(dev);
+	int ret = 0;
+
+	spear_rtc_clear_interrupt(config);
+
+	switch (enabled) {
+	case 0:
+		/* alarm off */
+		spear_rtc_disable_interrupt(config);
+		break;
+	case 1:
+		/* alarm on */
+		spear_rtc_enable_interrupt(config);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static struct rtc_class_ops spear_rtc_ops = {
 	.read_time = spear_rtc_read_time,
 	.set_time = spear_rtc_set_time,
 	.read_alarm = spear_rtc_read_alarm,
 	.set_alarm = spear_rtc_set_alarm,
+	.alarm_irq_enable = spear_alarm_irq_enable,
 };
 
 static int __devinit spear_rtc_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	struct rtc_device *rtc;
 	struct spear_rtc_config *config;
 	unsigned int status = 0;
 	int irq;
@@ -376,19 +394,17 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 	}
 
 	spin_lock_init(&config->lock);
+	platform_set_drvdata(pdev, config);
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev, &spear_rtc_ops,
-			THIS_MODULE);
-	if (IS_ERR(rtc)) {
+	config->rtc = rtc_device_register(pdev->name, &pdev->dev,
+			&spear_rtc_ops, THIS_MODULE);
+	if (IS_ERR(config->rtc)) {
 		dev_err(&pdev->dev, "can't register RTC device, err %ld\n",
-				PTR_ERR(rtc));
-		status = PTR_ERR(rtc);
+				PTR_ERR(config->rtc));
+		status = PTR_ERR(config->rtc);
 		goto err_iounmap;
 	}
 
-	platform_set_drvdata(pdev, rtc);
-	dev_set_drvdata(&rtc->dev, config);
-
 	/* alarm irqs */
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -397,7 +413,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 		goto err_clear_platdata;
 	}
 
-	status = request_irq(irq, spear_rtc_irq, 0, pdev->name, rtc);
+	status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config);
 	if (status) {
 		dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \
 				claimed\n", irq);
@@ -411,8 +427,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev)
 
 err_clear_platdata:
 	platform_set_drvdata(pdev, NULL);
-	dev_set_drvdata(&rtc->dev, NULL);
-	rtc_device_unregister(rtc);
+	rtc_device_unregister(config->rtc);
 err_iounmap:
 	iounmap(config->ioaddr);
 err_disable_clock:
@@ -429,8 +444,7 @@ err_release_region:
 
 static int __devexit spear_rtc_remove(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = platform_get_drvdata(pdev);
 	int irq;
 	struct resource *res;
 
@@ -448,8 +462,7 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev)
 	if (res)
 		release_mem_region(res->start, resource_size(res));
 	platform_set_drvdata(pdev, NULL);
-	dev_set_drvdata(&rtc->dev, NULL);
-	rtc_device_unregister(rtc);
+	rtc_device_unregister(config->rtc);
 
 	return 0;
 }
@@ -458,14 +471,14 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev)
 
 static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = platform_get_drvdata(pdev);
 	int irq;
 
 	irq = platform_get_irq(pdev, 0);
-	if (device_may_wakeup(&pdev->dev))
-		enable_irq_wake(irq);
-	else {
+	if (device_may_wakeup(&pdev->dev)) {
+		if (!enable_irq_wake(irq))
+			config->irq_wake = 1;
+	} else {
 		spear_rtc_disable_interrupt(config);
 		clk_disable(config->clk);
 	}
@@ -475,15 +488,17 @@ static int spear_rtc_suspend(struct platform_device *pdev, pm_message_t state)
 
 static int spear_rtc_resume(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = platform_get_drvdata(pdev);
 	int irq;
 
 	irq = platform_get_irq(pdev, 0);
 
-	if (device_may_wakeup(&pdev->dev))
-		disable_irq_wake(irq);
-	else {
+	if (device_may_wakeup(&pdev->dev)) {
+		if (config->irq_wake) {
+			disable_irq_wake(irq);
+			config->irq_wake = 0;
+		}
+	} else {
 		clk_enable(config->clk);
 		spear_rtc_enable_interrupt(config);
 	}
@@ -498,8 +513,7 @@ static int spear_rtc_resume(struct platform_device *pdev)
 
 static void spear_rtc_shutdown(struct platform_device *pdev)
 {
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-	struct spear_rtc_config *config = dev_get_drvdata(&rtc->dev);
+	struct spear_rtc_config *config = platform_get_drvdata(pdev);
 
 	spear_rtc_disable_interrupt(config);
 	clk_disable(config->clk);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index eef27a1..110137e 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3261,6 +3261,12 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
 			device->path_data.tbvpm |= eventlpm;
 			dasd_schedule_device_bh(device);
 		}
+		if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+			DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+				      "Pathgroup re-established\n");
+			if (device->discipline->kick_validate)
+				device->discipline->kick_validate(device);
+		}
 	}
 	dasd_put_device(device);
 }
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 553b3c5..b3beed5 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -189,14 +189,12 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
 	unsigned long flags;
 	struct alias_server *server, *newserver;
 	struct alias_lcu *lcu, *newlcu;
-	int is_lcu_known;
 	struct dasd_uid uid;
 
 	private = (struct dasd_eckd_private *) device->private;
 
 	device->discipline->get_uid(device, &uid);
 	spin_lock_irqsave(&aliastree.lock, flags);
-	is_lcu_known = 1;
 	server = _find_server(&uid);
 	if (!server) {
 		spin_unlock_irqrestore(&aliastree.lock, flags);
@@ -208,7 +206,6 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
 		if (!server) {
 			list_add(&newserver->server, &aliastree.serverlist);
 			server = newserver;
-			is_lcu_known = 0;
 		} else {
 			/* someone was faster */
 			_free_server(newserver);
@@ -226,12 +223,10 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
 		if (!lcu) {
 			list_add(&newlcu->lcu, &server->lculist);
 			lcu = newlcu;
-			is_lcu_known = 0;
 		} else {
 			/* someone was faster */
 			_free_lcu(newlcu);
 		}
-		is_lcu_known = 0;
 	}
 	spin_lock(&lcu->lock);
 	list_add(&device->alias_list, &lcu->inactive_devices);
@@ -239,64 +234,7 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device)
 	spin_unlock(&lcu->lock);
 	spin_unlock_irqrestore(&aliastree.lock, flags);
 
-	return is_lcu_known;
-}
-
-/*
- * The first device to be registered on an LCU will have to do
- * some additional setup steps to configure that LCU on the
- * storage server. All further devices should wait with their
- * initialization until the first device is done.
- * To synchronize this work, the first device will call
- * dasd_alias_lcu_setup_complete when it is done, and all
- * other devices will wait for it with dasd_alias_wait_for_lcu_setup.
- */
-void dasd_alias_lcu_setup_complete(struct dasd_device *device)
-{
-	unsigned long flags;
-	struct alias_server *server;
-	struct alias_lcu *lcu;
-	struct dasd_uid uid;
-
-	device->discipline->get_uid(device, &uid);
-	lcu = NULL;
-	spin_lock_irqsave(&aliastree.lock, flags);
-	server = _find_server(&uid);
-	if (server)
-		lcu = _find_lcu(server, &uid);
-	spin_unlock_irqrestore(&aliastree.lock, flags);
-	if (!lcu) {
-		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
-				"could not find lcu for %04x %02x",
-				uid.ssid, uid.real_unit_addr);
-		WARN_ON(1);
-		return;
-	}
-	complete_all(&lcu->lcu_setup);
-}
-
-void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
-{
-	unsigned long flags;
-	struct alias_server *server;
-	struct alias_lcu *lcu;
-	struct dasd_uid uid;
-
-	device->discipline->get_uid(device, &uid);
-	lcu = NULL;
-	spin_lock_irqsave(&aliastree.lock, flags);
-	server = _find_server(&uid);
-	if (server)
-		lcu = _find_lcu(server, &uid);
-	spin_unlock_irqrestore(&aliastree.lock, flags);
-	if (!lcu) {
-		DBF_EVENT_DEVID(DBF_ERR, device->cdev,
-				"could not find lcu for %04x %02x",
-				uid.ssid, uid.real_unit_addr);
-		WARN_ON(1);
-		return;
-	}
-	wait_for_completion(&lcu->lcu_setup);
+	return 0;
 }
 
 /*
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index bbcd5e9..70880be 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1534,6 +1534,10 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
 	struct dasd_eckd_private *private;
 	int enable_pav;
 
+	private = (struct dasd_eckd_private *) device->private;
+	if (private->uid.type == UA_BASE_PAV_ALIAS ||
+	    private->uid.type == UA_HYPER_PAV_ALIAS)
+		return;
 	if (dasd_nopav || MACHINE_IS_VM)
 		enable_pav = 0;
 	else
@@ -1542,11 +1546,28 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
 
 	/* may be requested feature is not available on server,
 	 * therefore just report error and go ahead */
-	private = (struct dasd_eckd_private *) device->private;
 	DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
 			"returned rc=%d", private->uid.ssid, rc);
 }
 
+/*
+ * worker to do a validate server in case of a lost pathgroup
+ */
+static void dasd_eckd_do_validate_server(struct work_struct *work)
+{
+	struct dasd_device *device = container_of(work, struct dasd_device,
+						  kick_validate);
+	dasd_eckd_validate_server(device);
+	dasd_put_device(device);
+}
+
+static void dasd_eckd_kick_validate_server(struct dasd_device *device)
+{
+	dasd_get_device(device);
+	/* queue call to do_validate_server to the kernel event daemon. */
+	schedule_work(&device->kick_validate);
+}
+
 static u32 get_fcx_max_data(struct dasd_device *device)
 {
 #if defined(CONFIG_64BIT)
@@ -1588,10 +1609,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
 	struct dasd_eckd_private *private;
 	struct dasd_block *block;
 	struct dasd_uid temp_uid;
-	int is_known, rc, i;
+	int rc, i;
 	int readonly;
 	unsigned long value;
 
+	/* setup work queue for validate server*/
+	INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server);
+
 	if (!ccw_device_is_pathgroup(device->cdev)) {
 		dev_warn(&device->cdev->dev,
 			 "A channel path group could not be established\n");
@@ -1651,22 +1675,12 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
 		block->base = device;
 	}
 
-	/* register lcu with alias handling, enable PAV if this is a new lcu */
-	is_known = dasd_alias_make_device_known_to_lcu(device);
-	if (is_known < 0) {
-		rc = is_known;
+	/* register lcu with alias handling, enable PAV */
+	rc = dasd_alias_make_device_known_to_lcu(device);
+	if (rc)
 		goto out_err2;
-	}
-	/*
-	 * dasd_eckd_validate_server is done on the first device that
-	 * is found for an LCU. All later other devices have to wait
-	 * for it, so they will read the correct feature codes.
-	 */
-	if (!is_known) {
-		dasd_eckd_validate_server(device);
-		dasd_alias_lcu_setup_complete(device);
-	} else
-		dasd_alias_wait_for_lcu_setup(device);
+
+	dasd_eckd_validate_server(device);
 
 	/* device may report different configuration data after LCU setup */
 	rc = dasd_eckd_read_conf(device);
@@ -4098,7 +4112,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
 {
 	struct dasd_eckd_private *private;
 	struct dasd_eckd_characteristics temp_rdc_data;
-	int is_known, rc;
+	int rc;
 	struct dasd_uid temp_uid;
 	unsigned long flags;
 
@@ -4121,14 +4135,10 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
 		goto out_err;
 
 	/* register lcu with alias handling, enable PAV if this is a new lcu */
-	is_known = dasd_alias_make_device_known_to_lcu(device);
-	if (is_known < 0)
-		return is_known;
-	if (!is_known) {
-		dasd_eckd_validate_server(device);
-		dasd_alias_lcu_setup_complete(device);
-	} else
-		dasd_alias_wait_for_lcu_setup(device);
+	rc = dasd_alias_make_device_known_to_lcu(device);
+	if (rc)
+		return rc;
+	dasd_eckd_validate_server(device);
 
 	/* RE-Read Configuration Data */
 	rc = dasd_eckd_read_conf(device);
@@ -4270,6 +4280,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
 	.restore = dasd_eckd_restore_device,
 	.reload = dasd_eckd_reload_device,
 	.get_uid = dasd_eckd_get_uid,
+	.kick_validate = dasd_eckd_kick_validate_server,
 };
 
 static int __init
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index afe8c33..33a6743 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -355,6 +355,7 @@ struct dasd_discipline {
 	int (*reload) (struct dasd_device *);
 
 	int (*get_uid) (struct dasd_device *, struct dasd_uid *);
+	void (*kick_validate) (struct dasd_device *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -455,6 +456,7 @@ struct dasd_device {
 	struct work_struct kick_work;
 	struct work_struct restore_device;
 	struct work_struct reload_device;
+	struct work_struct kick_validate;
 	struct timer_list timer;
 
 	debug_info_t *debug_area;
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 0b54a91..168525a 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -441,9 +441,8 @@ static int sclp_mem_notifier(struct notifier_block *nb,
 	start = arg->start_pfn << PAGE_SHIFT;
 	size = arg->nr_pages << PAGE_SHIFT;
 	mutex_lock(&sclp_mem_mutex);
-	for (id = 0; id <= sclp_max_storage_id; id++)
-		if (!test_bit(id, sclp_storage_ids))
-			sclp_attach_storage(id);
+	for_each_clear_bit(id, sclp_storage_ids, sclp_max_storage_id + 1)
+		sclp_attach_storage(id);
 	switch (action) {
 	case MEM_ONLINE:
 	case MEM_GOING_OFFLINE:
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 0bd38da..fac1757 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -701,6 +701,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
 				     AAC_OPT_NEW_COMM) ?
 				      (dev->scsi_host_ptr->max_sectors << 9) :
 				      65536)) {
+					kfree(usg);
 					rcode = -EINVAL;
 					goto cleanup;
 				}
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index f980600..2fe9e90 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1736,7 +1736,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
 						(uint32_t ) cmd->cmnd[8];
 						/* 4 bytes: Areca io control code */
 	sg = scsi_sglist(cmd);
-	buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+	buffer = kmap_atomic(sg_page(sg)) + sg->offset;
 	if (scsi_sg_count(cmd) > 1) {
 		retvalue = ARCMSR_MESSAGE_FAIL;
 		goto message_out;
@@ -1985,7 +1985,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
 	}
 	message_out:
 	sg = scsi_sglist(cmd);
-	kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+	kunmap_atomic(buffer - sg->offset);
 	return retvalue;
 }
 
@@ -2035,11 +2035,11 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
 
 		sg = scsi_sglist(cmd);
-		buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+		buffer = kmap_atomic(sg_page(sg)) + sg->offset;
 
 		memcpy(buffer, inqdata, sizeof(inqdata));
 		sg = scsi_sglist(cmd);
-		kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+		kunmap_atomic(buffer - sg->offset);
 
 		cmd->scsi_done(cmd);
 	}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 8c6156a..a9af42e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -322,8 +322,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
 			return -ENOMEM;
 		}
 		frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
-		cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
-				+ frag->page_offset;
+		cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset;
 	} else {
 		cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
 	}
@@ -332,7 +331,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
 	cp->fcoe_eof = eof;
 	cp->fcoe_crc32 = cpu_to_le32(~crc);
 	if (skb_is_nonlinear(skb)) {
-		kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
+		kunmap_atomic(cp);
 		cp = NULL;
 	}
 
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index d3ff9cd..89afd6d 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -1956,12 +1956,11 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
 
 			/* data fits in the skb's headroom */
 			for (i = 0; i < tdata->nr_frags; i++, frag++) {
-				char *src = kmap_atomic(frag->page,
-							KM_SOFTIRQ0);
+				char *src = kmap_atomic(frag->page);
 
 				memcpy(dst, src+frag->offset, frag->size);
 				dst += frag->size;
-				kunmap_atomic(src, KM_SOFTIRQ0);
+				kunmap_atomic(src);
 			}
 			if (padlen) {
 				memset(dst, 0, padlen);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index e959960..1094357 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1515,7 +1515,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 			return -ENOMEM;
 		}
 		frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
-		cp = kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ)
+		cp = kmap_atomic(skb_frag_page(frag))
 			+ frag->page_offset;
 	} else {
 		cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
@@ -1526,7 +1526,7 @@ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 	cp->fcoe_crc32 = cpu_to_le32(~crc);
 
 	if (skb_is_nonlinear(skb)) {
-		kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
+		kunmap_atomic(cp);
 		cp = NULL;
 	}
 
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
index bd97b22..4d119a3 100644
--- a/drivers/scsi/fcoe/fcoe_transport.c
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -210,10 +210,9 @@ u32 fcoe_fc_crc(struct fc_frame *fp)
 		while (len > 0) {
 			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
 			data = kmap_atomic(
-				skb_frag_page(frag) + (off >> PAGE_SHIFT),
-				KM_SKB_DATA_SOFTIRQ);
+				skb_frag_page(frag) + (off >> PAGE_SHIFT));
 			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
-			kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
+			kunmap_atomic(data);
 			off += clen;
 			len -= clen;
 		}
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 3242bca..d42ec92 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2310,10 +2310,10 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
                 return;
             }
             local_irq_save(flags);
-            address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset;
+            address = kmap_atomic(sg_page(sl)) + sl->offset;
             memcpy(address, buffer, cpnow);
             flush_dcache_page(sg_page(sl));
-            kunmap_atomic(address, KM_BIO_SRC_IRQ);
+            kunmap_atomic(address);
             local_irq_restore(flags);
             if (cpsum == cpcount)
                 break;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index d77891e..b6d7a5c 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1511,14 +1511,14 @@ static int ips_is_passthru(struct scsi_cmnd *SC)
                 /* kmap_atomic() ensures addressability of the user buffer.*/
                 /* local_irq_save() protects the KM_IRQ0 address slot.     */
                 local_irq_save(flags);
-                buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+                buffer = kmap_atomic(sg_page(sg)) + sg->offset;
                 if (buffer && buffer[0] == 'C' && buffer[1] == 'O' &&
                     buffer[2] == 'P' && buffer[3] == 'P') {
-                        kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                        kunmap_atomic(buffer - sg->offset);
                         local_irq_restore(flags);
                         return 1;
                 }
-                kunmap_atomic(buffer - sg->offset, KM_IRQ0);
+                kunmap_atomic(buffer - sg->offset);
                 local_irq_restore(flags);
 	}
 	return 0;
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c
index 192cb48..ee0dc05 100644
--- a/drivers/scsi/isci/request.c
+++ b/drivers/scsi/isci/request.c
@@ -1304,9 +1304,9 @@ sci_stp_request_pio_data_in_copy_data_buffer(struct isci_stp_request *stp_req,
 			struct page *page = sg_page(sg);
 
 			copy_len = min_t(int, total_len, sg_dma_len(sg));
-			kaddr = kmap_atomic(page, KM_IRQ0);
+			kaddr = kmap_atomic(page);
 			memcpy(kaddr + sg->offset, src_addr, copy_len);
-			kunmap_atomic(kaddr, KM_IRQ0);
+			kunmap_atomic(kaddr);
 			total_len -= copy_len;
 			src_addr += copy_len;
 			sg = sg_next(sg);
@@ -1654,7 +1654,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
 		sci_unsolicited_frame_control_get_header(&ihost->uf_control,
 							 frame_index,
 							 &frame_header);
-		kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
+		kaddr = kmap_atomic(sg_page(sg));
 		rsp = kaddr + sg->offset;
 		sci_swab32_cpy(rsp, frame_header, 1);
 
@@ -1691,7 +1691,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
 			ireq->sci_status = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR;
 			sci_change_state(&ireq->sm, SCI_REQ_COMPLETED);
 		}
-		kunmap_atomic(kaddr, KM_IRQ0);
+		kunmap_atomic(kaddr);
 
 		sci_controller_release_frame(ihost, frame_index);
 
@@ -3023,10 +3023,10 @@ static void isci_request_io_request_complete(struct isci_host *ihost,
 		dma_unmap_sg(&ihost->pdev->dev, sg, 1, DMA_TO_DEVICE);
 
 		/* need to swab it back in case the command buffer is re-used */
-		kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
+		kaddr = kmap_atomic(sg_page(sg));
 		smp_req = kaddr + sg->offset;
 		sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32));
-		kunmap_atomic(kaddr, KM_IRQ0);
+		kunmap_atomic(kaddr);
 		break;
 	}
 	default:
@@ -3311,7 +3311,7 @@ sci_io_request_construct_smp(struct device *dev,
 	u8 req_len;
 	u32 cmd;
 
-	kaddr = kmap_atomic(sg_page(sg), KM_IRQ0);
+	kaddr = kmap_atomic(sg_page(sg));
 	smp_req = kaddr + sg->offset;
 	/*
 	 * Look at the SMP requests' header fields; for certain SAS 1.x SMP
@@ -3337,7 +3337,7 @@ sci_io_request_construct_smp(struct device *dev,
 	req_len = smp_req->req_len;
 	sci_swab32_cpy(smp_req, smp_req, sg->length / sizeof(u32));
 	cmd = *(u32 *) smp_req;
-	kunmap_atomic(kaddr, KM_IRQ0);
+	kunmap_atomic(kaddr);
 
 	if (!dma_map_sg(dev, sg, 1, DMA_TO_DEVICE))
 		return SCI_FAILURE;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f607314..b577c90 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -485,11 +485,11 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
 
 	if (!(fr_flags(fp) & FCPHF_CRC_UNCHECKED)) {
 		copy_len = fc_copy_buffer_to_sglist(buf, len, sg, &nents,
-						    &offset, KM_SOFTIRQ0, NULL);
+						    &offset, NULL);
 	} else {
 		crc = crc32(~0, (u8 *) fh, sizeof(*fh));
 		copy_len = fc_copy_buffer_to_sglist(buf, len, sg, &nents,
-						    &offset, KM_SOFTIRQ0, &crc);
+						    &offset, &crc);
 		buf = fc_frame_payload_get(fp, 0);
 		if (len % 4)
 			crc = crc32(crc, buf + len, 4 - (len % 4));
@@ -650,10 +650,10 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
 			 * The scatterlist item may be bigger than PAGE_SIZE,
 			 * but we must not cross pages inside the kmap.
 			 */
-			page_addr = kmap_atomic(page, KM_SOFTIRQ0);
+			page_addr = kmap_atomic(page);
 			memcpy(data, (char *)page_addr + (off & ~PAGE_MASK),
 			       sg_bytes);
-			kunmap_atomic(page_addr, KM_SOFTIRQ0);
+			kunmap_atomic(page_addr);
 			data += sg_bytes;
 		}
 		offset += sg_bytes;
diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c
index 1bf9841..8d65a51a 100644
--- a/drivers/scsi/libfc/fc_libfc.c
+++ b/drivers/scsi/libfc/fc_libfc.c
@@ -105,14 +105,13 @@ module_exit(libfc_exit);
  * @sg: pointer to the pointer of the SG list.
  * @nents: pointer to the remaining number of entries in the SG list.
  * @offset: pointer to the current offset in the SG list.
- * @km_type: dedicated page table slot type for kmap_atomic.
  * @crc: pointer to the 32-bit crc value.
  *	 If crc is NULL, CRC is not calculated.
  */
 u32 fc_copy_buffer_to_sglist(void *buf, size_t len,
 			     struct scatterlist *sg,
 			     u32 *nents, size_t *offset,
-			     enum km_type km_type, u32 *crc)
+			     u32 *crc)
 {
 	size_t remaining = len;
 	u32 copy_len = 0;
@@ -142,12 +141,11 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len,
 		off = *offset + sg->offset;
 		sg_bytes = min(sg_bytes,
 			       (size_t)(PAGE_SIZE - (off & ~PAGE_MASK)));
-		page_addr = kmap_atomic(sg_page(sg) + (off >> PAGE_SHIFT),
-					km_type);
+		page_addr = kmap_atomic(sg_page(sg) + (off >> PAGE_SHIFT));
 		if (crc)
 			*crc = crc32(*crc, buf, sg_bytes);
 		memcpy((char *)page_addr + (off & ~PAGE_MASK), buf, sg_bytes);
-		kunmap_atomic(page_addr, km_type);
+		kunmap_atomic(page_addr);
 		buf += sg_bytes;
 		*offset += sg_bytes;
 		remaining -= sg_bytes;
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index c7d0712..c2830cc 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -134,6 +134,6 @@ extern void fc_fc4_conf_lport_params(struct fc_lport *, enum fc_fh_type);
 u32 fc_copy_buffer_to_sglist(void *buf, size_t len,
 			     struct scatterlist *sg,
 			     u32 *nents, size_t *offset,
-			     enum km_type km_type, u32 *crc);
+			     u32 *crc);
 
 #endif /* _FC_LIBFC_H_ */
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 83750eb..c1a808c 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1698,7 +1698,7 @@ static void fc_lport_bsg_resp(struct fc_seq *sp, struct fc_frame *fp,
 
 	job->reply->reply_payload_rcv_len +=
 		fc_copy_buffer_to_sglist(buf, len, info->sg, &info->nents,
-					 &info->offset, KM_BIO_SRC_IRQ, NULL);
+					 &info->offset, NULL);
 
 	if (fr_eof(fp) == FC_EOF_T &&
 	    (ntoh24(fh->fh_f_ctl) & (FC_FC_LAST_SEQ | FC_FC_END_SEQ)) ==
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index 5715a3d..7f0465b 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -135,7 +135,7 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
 
 	if (recv) {
 		segment->atomic_mapped = true;
-		segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+		segment->sg_mapped = kmap_atomic(sg_page(sg));
 	} else {
 		segment->atomic_mapped = false;
 		/* the xmit path can sleep with the page mapped so use kmap */
@@ -149,7 +149,7 @@ void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
 {
 	if (segment->sg_mapped) {
 		if (segment->atomic_mapped)
-			kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
+			kunmap_atomic(segment->sg_mapped);
 		else
 			kunmap(sg_page(segment->sg));
 		segment->sg_mapped = NULL;
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index bb8f492..3814d3e 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -246,9 +246,9 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
 	}
 
 	local_irq_disable();
-	buf = kmap_atomic(bio_page(req->bio), KM_USER0) + bio_offset(req->bio);
+	buf = kmap_atomic(bio_page(req->bio));
 	memcpy(req_data, buf, blk_rq_bytes(req));
-	kunmap_atomic(buf - bio_offset(req->bio), KM_USER0);
+	kunmap_atomic(buf - bio_offset(req->bio));
 	local_irq_enable();
 
 	if (req_data[0] != SMP_REQUEST)
@@ -361,10 +361,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
 	}
 
 	local_irq_disable();
-	buf = kmap_atomic(bio_page(rsp->bio), KM_USER0) + bio_offset(rsp->bio);
+	buf = kmap_atomic(bio_page(rsp->bio));
 	memcpy(buf, resp_data, blk_rq_bytes(rsp));
 	flush_kernel_dcache_page(bio_page(rsp->bio));
-	kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0);
+	kunmap_atomic(buf - bio_offset(rsp->bio));
 	local_irq_enable();
 
  out:
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 15eefa1..4d39a9f 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -670,10 +670,10 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy)
 			struct scatterlist *sg;
 
 			sg = scsi_sglist(cmd);
-			buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
+			buf = kmap_atomic(sg_page(sg)) + sg->offset;
 
 			memset(buf, 0, cmd->cmnd[4]);
-			kunmap_atomic(buf - sg->offset, KM_IRQ0);
+			kunmap_atomic(buf - sg->offset);
 
 			cmd->result = (DID_OK << 16);
 			cmd->scsi_done(cmd);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 0b2c955..a78036f 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -4548,7 +4548,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
 		printk(MPT2SAS_ERR_FMT "%s: pci error recovery reset\n",
 		    ioc->name, __func__);
 		r = 0;
-		goto out;
+		goto out_unlocked;
 	}
 
 	if (mpt2sas_fwfault_debug)
@@ -4604,6 +4604,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
 	spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 	mutex_unlock(&ioc->reset_in_progress_mutex);
 
+ out_unlocked:
 	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit\n", ioc->name,
 	    __func__));
 	return r;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 193e33e..d953a57 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -5744,7 +5744,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
 }
 
 /**
- * _scsih_sas_broadcast_primative_event - handle broadcast events
+ * _scsih_sas_broadcast_primitive_event - handle broadcast events
  * @ioc: per adapter object
  * @fw_event: The fw_event_work object
  * Context: user.
@@ -5752,7 +5752,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
  * Return nothing.
  */
 static void
-_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc,
+_scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc,
     struct fw_event_work *fw_event)
 {
 	struct scsi_cmnd *scmd;
@@ -7263,7 +7263,7 @@ _firmware_event_work(struct work_struct *work)
 		    fw_event);
 		break;
 	case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
-		_scsih_sas_broadcast_primative_event(ioc,
+		_scsih_sas_broadcast_primitive_event(ioc,
 		    fw_event);
 		break;
 	case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
index a4884a5..01ab9c4 100644
--- a/drivers/scsi/mvsas/mv_sas.c
+++ b/drivers/scsi/mvsas/mv_sas.c
@@ -1885,11 +1885,11 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
 	case SAS_PROTOCOL_SMP: {
 			struct scatterlist *sg_resp = &task->smp_task.smp_resp;
 			tstat->stat = SAM_STAT_GOOD;
-			to = kmap_atomic(sg_page(sg_resp), KM_IRQ0);
+			to = kmap_atomic(sg_page(sg_resp));
 			memcpy(to + sg_resp->offset,
 				slot->response + sizeof(struct mvs_err_info),
 				sg_dma_len(sg_resp));
-			kunmap_atomic(to, KM_IRQ0);
+			kunmap_atomic(to);
 			break;
 		}
 
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6888b2c..68da6c0 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1778,7 +1778,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 	scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) {
 		int len = min(psgl->length, resid);
 
-		paddr = kmap_atomic(sg_page(psgl), KM_IRQ0) + psgl->offset;
+		paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
 		memcpy(paddr, dif_storep + dif_offset(sector), len);
 
 		sector += len >> 3;
@@ -1788,7 +1788,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
 			sector = do_div(tmp_sec, sdebug_store_sectors);
 		}
 		resid -= len;
-		kunmap_atomic(paddr, KM_IRQ0);
+		kunmap_atomic(paddr);
 	}
 
 	dix_reads++;
@@ -1881,12 +1881,12 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 	BUG_ON(scsi_sg_count(SCpnt) == 0);
 	BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
 
-	paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + psgl->offset;
+	paddr = kmap_atomic(sg_page(psgl)) + psgl->offset;
 	ppage_offset = 0;
 
 	/* For each data page */
 	scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) {
-		daddr = kmap_atomic(sg_page(dsgl), KM_IRQ0) + dsgl->offset;
+		daddr = kmap_atomic(sg_page(dsgl)) + dsgl->offset;
 
 		/* For each sector-sized chunk in data page */
 		for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) {
@@ -1895,10 +1895,10 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 			 * protection page advance to the next one
 			 */
 			if (ppage_offset >= psgl->length) {
-				kunmap_atomic(paddr, KM_IRQ1);
+				kunmap_atomic(paddr);
 				psgl = sg_next(psgl);
 				BUG_ON(psgl == NULL);
-				paddr = kmap_atomic(sg_page(psgl), KM_IRQ1)
+				paddr = kmap_atomic(sg_page(psgl))
 					+ psgl->offset;
 				ppage_offset = 0;
 			}
@@ -1971,10 +1971,10 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 			ppage_offset += sizeof(struct sd_dif_tuple);
 		}
 
-		kunmap_atomic(daddr, KM_IRQ0);
+		kunmap_atomic(daddr);
 	}
 
-	kunmap_atomic(paddr, KM_IRQ1);
+	kunmap_atomic(paddr);
 
 	dix_writes++;
 
@@ -1982,8 +1982,8 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 
 out:
 	dif_errors++;
-	kunmap_atomic(daddr, KM_IRQ0);
-	kunmap_atomic(paddr, KM_IRQ1);
+	kunmap_atomic(daddr);
+	kunmap_atomic(paddr);
 	return ret;
 }
 
@@ -2303,7 +2303,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
 
 	offset = 0;
 	for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
-		kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);
+		kaddr = (unsigned char *)kmap_atomic(sg_page(sg));
 		if (!kaddr)
 			goto out;
 
@@ -2311,7 +2311,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba,
 			*(kaddr + sg->offset + j) ^= *(buf + offset + j);
 
 		offset += sg->length;
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 	ret = 0;
 out:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b2c95db..a33b2b6 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -2567,7 +2567,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
 	if (*len > sg_len)
 		*len = sg_len;
 
-	return kmap_atomic(page, KM_BIO_SRC_IRQ);
+	return kmap_atomic(page);
 }
 EXPORT_SYMBOL(scsi_kmap_atomic_sg);
 
@@ -2577,6 +2577,6 @@ EXPORT_SYMBOL(scsi_kmap_atomic_sg);
  */
 void scsi_kunmap_atomic_sg(void *virt)
 {
-	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+	kunmap_atomic(virt);
 }
 EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c
index 0cb39ff..e981d97 100644
--- a/drivers/scsi/sd_dif.c
+++ b/drivers/scsi/sd_dif.c
@@ -392,7 +392,7 @@ int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_s
 		virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 		bip_for_each_vec(iv, bio->bi_integrity, i) {
-			sdt = kmap_atomic(iv->bv_page, KM_USER0)
+			sdt = kmap_atomic(iv->bv_page)
 				+ iv->bv_offset;
 
 			for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
@@ -405,7 +405,7 @@ int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_s
 				phys++;
 			}
 
-			kunmap_atomic(sdt, KM_USER0);
+			kunmap_atomic(sdt);
 		}
 
 		bio->bi_flags |= BIO_MAPPED_INTEGRITY;
@@ -414,7 +414,7 @@ int sd_dif_prepare(struct request *rq, sector_t hw_sector, unsigned int sector_s
 	return 0;
 
 error:
-	kunmap_atomic(sdt, KM_USER0);
+	kunmap_atomic(sdt);
 	sd_printk(KERN_ERR, sdkp, "%s: virt %u, phys %u, ref %u, app %4x\n",
 		  __func__, virt, phys, be32_to_cpu(sdt->ref_tag),
 		  be16_to_cpu(sdt->app_tag));
@@ -453,13 +453,13 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
 		virt = bio->bi_integrity->bip_sector & 0xffffffff;
 
 		bip_for_each_vec(iv, bio->bi_integrity, i) {
-			sdt = kmap_atomic(iv->bv_page, KM_USER0)
+			sdt = kmap_atomic(iv->bv_page)
 				+ iv->bv_offset;
 
 			for (j = 0 ; j < iv->bv_len ; j += tuple_sz, sdt++) {
 
 				if (sectors == 0) {
-					kunmap_atomic(sdt, KM_USER0);
+					kunmap_atomic(sdt);
 					return;
 				}
 
@@ -474,7 +474,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes)
 				sectors--;
 			}
 
-			kunmap_atomic(sdt, KM_USER0);
+			kunmap_atomic(sdt);
 		}
 	}
 }
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
index c904d73..e80ee82 100644
--- a/drivers/staging/gma500/mmu.c
+++ b/drivers/staging/gma500/mmu.c
@@ -125,14 +125,14 @@ static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
 	int i;
 	uint8_t *clf;
 
-	clf = kmap_atomic(page, KM_USER0);
+	clf = kmap_atomic(page);
 	mb();
 	for (i = 0; i < clflush_count; ++i) {
 		psb_clflush(clf);
 		clf += clflush_add;
 	}
 	mb();
-	kunmap_atomic(clf, KM_USER0);
+	kunmap_atomic(clf);
 }
 
 static void psb_pages_clflush(struct psb_mmu_driver *driver,
@@ -325,7 +325,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
 
 	spin_lock(lock);
 
-	v = kmap_atomic(pt->p, KM_USER0);
+	v = kmap_atomic(pt->p);
 	clf = (uint8_t *) v;
 	ptes = (uint32_t *) v;
 	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
@@ -341,7 +341,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
 		mb();
 	}
 
-	kunmap_atomic(v, KM_USER0);
+	kunmap_atomic(v);
 	spin_unlock(lock);
 
 	pt->count = 0;
@@ -376,18 +376,18 @@ struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
 			continue;
 		}
 
-		v = kmap_atomic(pd->p, KM_USER0);
+		v = kmap_atomic(pd->p);
 		pd->tables[index] = pt;
 		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
 		pt->index = index;
-		kunmap_atomic((void *) v, KM_USER0);
+		kunmap_atomic((void *) v);
 
 		if (pd->hw_context != -1) {
 			psb_mmu_clflush(pd->driver, (void *) &v[index]);
 			atomic_set(&pd->driver->needs_tlbflush, 1);
 		}
 	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
+	pt->v = kmap_atomic(pt->p);
 	return pt;
 }
 
@@ -404,7 +404,7 @@ static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
 		spin_unlock(lock);
 		return NULL;
 	}
-	pt->v = kmap_atomic(pt->p, KM_USER0);
+	pt->v = kmap_atomic(pt->p);
 	return pt;
 }
 
@@ -413,9 +413,9 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
 	struct psb_mmu_pd *pd = pt->pd;
 	uint32_t *v;
 
-	kunmap_atomic(pt->v, KM_USER0);
+	kunmap_atomic(pt->v);
 	if (pt->count == 0) {
-		v = kmap_atomic(pd->p, KM_USER0);
+		v = kmap_atomic(pd->p);
 		v[pt->index] = pd->invalid_pde;
 		pd->tables[pt->index] = NULL;
 
@@ -424,7 +424,7 @@ static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
 					(void *) &v[pt->index]);
 			atomic_set(&pd->driver->needs_tlbflush, 1);
 		}
-		kunmap_atomic(pt->v, KM_USER0);
+		kunmap_atomic(pt->v);
 		spin_unlock(&pd->driver->lock);
 		psb_mmu_free_pt(pt);
 		return;
@@ -457,7 +457,7 @@ void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
 	down_read(&driver->sem);
 	spin_lock(&driver->lock);
 
-	v = kmap_atomic(pd->p, KM_USER0);
+	v = kmap_atomic(pd->p);
 	v += start;
 
 	while (gtt_pages--) {
@@ -467,7 +467,7 @@ void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
 
 	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
 	psb_pages_clflush(pd->driver, &pd->p, num_pages);
-	kunmap_atomic(v, KM_USER0);
+	kunmap_atomic(v);
 	spin_unlock(&driver->lock);
 
 	if (pd->hw_context != -1)
@@ -830,9 +830,9 @@ int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
 		uint32_t *v;
 
 		spin_lock(lock);
-		v = kmap_atomic(pd->p, KM_USER0);
+		v = kmap_atomic(pd->p);
 		tmp = v[psb_mmu_pd_index(virtual)];
-		kunmap_atomic(v, KM_USER0);
+		kunmap_atomic(v);
 		spin_unlock(lock);
 
 		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index eb853f7..ddbdec8 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -941,15 +941,14 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 	local_irq_save(flags);
 
 	for (i = 0; i < orig_sgl_count; i++) {
-		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
-					KM_IRQ0) + orig_sgl[i].offset;
+		dest_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])))
+					+ orig_sgl[i].offset;
 		dest = dest_addr;
 		destlen = orig_sgl[i].length;
 
 		if (bounce_addr == 0)
 			bounce_addr =
-			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
-							KM_IRQ0);
+			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])));
 
 		while (destlen) {
 			src = bounce_addr + bounce_sgl[j].offset;
@@ -965,7 +964,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 
 			if (bounce_sgl[j].offset == bounce_sgl[j].length) {
 				/* full */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+				kunmap_atomic((void *)bounce_addr);
 				j++;
 
 				/*
@@ -990,15 +989,14 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl,
 				if (destlen || i != orig_sgl_count - 1)
 					bounce_addr =
 					(unsigned long)kmap_atomic(
-					sg_page((&bounce_sgl[j])), KM_IRQ0);
+					sg_page((&bounce_sgl[j])));
 			} else if (destlen == 0 && i == orig_sgl_count - 1) {
 				/* unmap the last bounce that is < PAGE_SIZE */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+				kunmap_atomic((void *)bounce_addr);
 			}
 		}
 
-		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset),
-			      KM_IRQ0);
+		kunmap_atomic((void *)(dest_addr - orig_sgl[i].offset));
 	}
 
 	local_irq_restore(flags);
@@ -1024,15 +1022,14 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 	local_irq_save(flags);
 
 	for (i = 0; i < orig_sgl_count; i++) {
-		src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])),
-				KM_IRQ0) + orig_sgl[i].offset;
+		src_addr = (unsigned long)kmap_atomic(sg_page((&orig_sgl[i])))
+				+ orig_sgl[i].offset;
 		src = src_addr;
 		srclen = orig_sgl[i].length;
 
 		if (bounce_addr == 0)
 			bounce_addr =
-			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])),
-						KM_IRQ0);
+			(unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])));
 
 		while (srclen) {
 			/* assume bounce offset always == 0 */
@@ -1049,22 +1046,22 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
 
 			if (bounce_sgl[j].length == PAGE_SIZE) {
 				/* full..move to next entry */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+				kunmap_atomic((void *)bounce_addr);
 				j++;
 
 				/* if we need to use another bounce buffer */
 				if (srclen || i != orig_sgl_count - 1)
 					bounce_addr =
 					(unsigned long)kmap_atomic(
-					sg_page((&bounce_sgl[j])), KM_IRQ0);
+					sg_page((&bounce_sgl[j])));
 
 			} else if (srclen == 0 && i == orig_sgl_count - 1) {
 				/* unmap the last bounce that is < PAGE_SIZE */
-				kunmap_atomic((void *)bounce_addr, KM_IRQ0);
+				kunmap_atomic((void *)bounce_addr);
 			}
 		}
 
-		kunmap_atomic((void *)(src_addr - orig_sgl[i].offset), KM_IRQ0);
+		kunmap_atomic((void *)(src_addr - orig_sgl[i].offset));
 	}
 
 	local_irq_restore(flags);
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 807e3f3..cbbae6c 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -606,11 +606,11 @@ static int pohmelfs_write_begin(struct file *file, struct address_space *mapping
 		}
 
 		if (len != PAGE_CACHE_SIZE) {
-			void *kaddr = kmap_atomic(page, KM_USER0);
+			void *kaddr = kmap_atomic(page);
 
 			memset(kaddr + start, 0, PAGE_CACHE_SIZE - start);
 			flush_dcache_page(page);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 		}
 		SetPageUptodate(page);
 	}
@@ -636,11 +636,11 @@ static int pohmelfs_write_end(struct file *file, struct address_space *mapping,
 
 	if (copied != len) {
 		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
-		void *kaddr = kmap_atomic(page, KM_USER0);
+		void *kaddr = kmap_atomic(page);
 
 		memset(kaddr + from + copied, 0, len - copied);
 		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 
 	SetPageUptodate(page);
diff --git a/drivers/staging/rtl8192u/ieee80211/cipher.c b/drivers/staging/rtl8192u/ieee80211/cipher.c
index 69dcc31..d47345c 100644
--- a/drivers/staging/rtl8192u/ieee80211/cipher.c
+++ b/drivers/staging/rtl8192u/ieee80211/cipher.c
@@ -71,8 +71,8 @@ static int crypt(struct crypto_tfm *tfm,
 		u8 *src_p, *dst_p;
 		int in_place;
 
-		scatterwalk_map(&walk_in, 0);
-		scatterwalk_map(&walk_out, 1);
+		scatterwalk_map(&walk_in);
+		scatterwalk_map(&walk_out);
 		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
 		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
 		in_place = scatterwalk_samebuf(&walk_in, &walk_out,
@@ -84,10 +84,10 @@ static int crypt(struct crypto_tfm *tfm,
 
 		prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
 
-		scatterwalk_done(&walk_in, 0, nbytes);
+		scatterwalk_done(&walk_in, nbytes);
 
 		scatterwalk_copychunks(dst_p, &walk_out, bsize, 1);
-		scatterwalk_done(&walk_out, 1, nbytes);
+		scatterwalk_done(&walk_out, nbytes);
 
 		if (!nbytes)
 			return 0;
diff --git a/drivers/staging/rtl8192u/ieee80211/digest.c b/drivers/staging/rtl8192u/ieee80211/digest.c
index 301ed51..05e7497 100644
--- a/drivers/staging/rtl8192u/ieee80211/digest.c
+++ b/drivers/staging/rtl8192u/ieee80211/digest.c
@@ -39,12 +39,12 @@ static void update(struct crypto_tfm *tfm,
 			unsigned int bytes_from_page = min(l, ((unsigned int)
 							   (PAGE_SIZE)) -
 							   offset);
-			char *p = crypto_kmap(pg, 0) + offset;
+			char *p = kmap_atomic(pg) + offset;
 
 			tfm->__crt_alg->cra_digest.dia_update
 					(crypto_tfm_ctx(tfm), p,
 					 bytes_from_page);
-			crypto_kunmap(p, 0);
+			kunmap_atomic(p);
 			crypto_yield(tfm);
 			offset = 0;
 			pg++;
@@ -75,10 +75,10 @@ static void digest(struct crypto_tfm *tfm,
 	tfm->crt_digest.dit_init(tfm);
 
 	for (i = 0; i < nsg; i++) {
-		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
+		char *p = kmap_atomic(sg[i].page) + sg[i].offset;
 		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
 						      p, sg[i].length);
-		crypto_kunmap(p, 0);
+		kunmap_atomic(p);
 		crypto_yield(tfm);
 	}
 	crypto_digest_final(tfm, out);
diff --git a/drivers/staging/rtl8192u/ieee80211/internal.h b/drivers/staging/rtl8192u/ieee80211/internal.h
index a7c096e..bebe13a 100644
--- a/drivers/staging/rtl8192u/ieee80211/internal.h
+++ b/drivers/staging/rtl8192u/ieee80211/internal.h
@@ -23,23 +23,6 @@
 #include <asm/kmap_types.h>
 
 
-extern enum km_type crypto_km_types[];
-
-static inline enum km_type crypto_kmap_type(int out)
-{
-	return crypto_km_types[(in_softirq() ? 2 : 0) + out];
-}
-
-static inline void *crypto_kmap(struct page *page, int out)
-{
-	return kmap_atomic(page, crypto_kmap_type(out));
-}
-
-static inline void crypto_kunmap(void *vaddr, int out)
-{
-	kunmap_atomic(vaddr, crypto_kmap_type(out));
-}
-
 static inline void crypto_yield(struct crypto_tfm *tfm)
 {
 	if (!in_softirq())
diff --git a/drivers/staging/rtl8192u/ieee80211/kmap_types.h b/drivers/staging/rtl8192u/ieee80211/kmap_types.h
deleted file mode 100644
index de67bb0..0000000
--- a/drivers/staging/rtl8192u/ieee80211/kmap_types.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __KMAP_TYPES_H
-
-#define __KMAP_TYPES_H
-
-
-enum km_type {
-	KM_BOUNCE_READ,
-	KM_SKB_SUNRPC_DATA,
-	KM_SKB_DATA_SOFTIRQ,
-	KM_USER0,
-	KM_USER1,
-	KM_BH_IRQ,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-	KM_TYPE_NR
-};
-
-#define _ASM_KMAP_TYPES_H
-
-#endif
diff --git a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c
index 3543a61..8b73f6c 100644
--- a/drivers/staging/rtl8192u/ieee80211/scatterwalk.c
+++ b/drivers/staging/rtl8192u/ieee80211/scatterwalk.c
@@ -13,8 +13,6 @@
  * any later version.
  *
  */
-#include "kmap_types.h"
-
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
@@ -23,13 +21,6 @@
 #include "internal.h"
 #include "scatterwalk.h"
 
-enum km_type crypto_km_types[] = {
-	KM_USER0,
-	KM_USER1,
-	KM_SOFTIRQ0,
-	KM_SOFTIRQ1,
-};
-
 void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch)
 {
 	if (nbytes <= walk->len_this_page &&
@@ -62,9 +53,9 @@ void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
 	walk->offset = sg->offset;
 }
 
-void scatterwalk_map(struct scatter_walk *walk, int out)
+void scatterwalk_map(struct scatter_walk *walk)
 {
-	walk->data = crypto_kmap(walk->page, out) + walk->offset;
+	walk->data = kmap_atomic(walk->page) + walk->offset;
 }
 
 static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
@@ -103,7 +94,7 @@ void scatterwalk_done(struct scatter_walk *walk, int out, int more)
  * has been verified as multiple of the block size.
  */
 int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
-			   size_t nbytes, int out)
+			   size_t nbytes)
 {
 	if (buf != walk->data) {
 		while (nbytes > walk->len_this_page) {
@@ -111,9 +102,9 @@ int scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
 			buf += walk->len_this_page;
 			nbytes -= walk->len_this_page;
 
-			crypto_kunmap(walk->data, out);
+			kunmap_atomic(walk->data);
 			scatterwalk_pagedone(walk, out, 1);
-			scatterwalk_map(walk, out);
+			scatterwalk_map(walk);
 		}
 
 		memcpy_dir(buf, walk->data, nbytes, out);
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index 642840c..57550ae 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -422,13 +422,13 @@ static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
 	}
 	ASSERT_SENTINEL(zh, ZBH);
 	BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size());
-	to_va = kmap_atomic(page, KM_USER0);
+	to_va = kmap_atomic(page);
 	size = zh->size;
 	from_va = zbud_data(zh, size);
 	ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len);
 	BUG_ON(ret != LZO_E_OK);
 	BUG_ON(out_len != PAGE_SIZE);
-	kunmap_atomic(to_va, KM_USER0);
+	kunmap_atomic(to_va);
 out:
 	spin_unlock(&zbpg->lock);
 	return ret;
@@ -677,13 +677,13 @@ static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
 		goto out;
 	zv_curr_dist_counts[chunks]++;
 	zv_cumul_dist_counts[chunks]++;
-	zv = kmap_atomic(page, KM_USER0) + offset;
+	zv = kmap_atomic(page) + offset;
 	zv->index = index;
 	zv->oid = *oid;
 	zv->pool_id = pool_id;
 	SET_SENTINEL(zv, ZVH);
 	memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen);
-	kunmap_atomic(zv, KM_USER0);
+	kunmap_atomic(zv);
 out:
 	return zv;
 }
@@ -719,10 +719,10 @@ static void zv_decompress(struct page *page, struct zv_hdr *zv)
 	ASSERT_SENTINEL(zv, ZVH);
 	size = xv_get_object_size(zv) - sizeof(*zv);
 	BUG_ON(size == 0);
-	to_va = kmap_atomic(page, KM_USER0);
+	to_va = kmap_atomic(page);
 	ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv),
 					size, to_va, &clen);
-	kunmap_atomic(to_va, KM_USER0);
+	kunmap_atomic(to_va);
 	BUG_ON(ret != LZO_E_OK);
 	BUG_ON(clen != PAGE_SIZE);
 }
@@ -1301,12 +1301,12 @@ static int zcache_compress(struct page *from, void **out_va, size_t *out_len)
 	BUG_ON(!irqs_disabled());
 	if (unlikely(dmem == NULL || wmem == NULL))
 		goto out;  /* no buffer, so can't compress */
-	from_va = kmap_atomic(from, KM_USER0);
+	from_va = kmap_atomic(from);
 	mb();
 	ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem);
 	BUG_ON(ret != LZO_E_OK);
 	*out_va = dmem;
-	kunmap_atomic(from_va, KM_USER0);
+	kunmap_atomic(from_va);
 	ret = 1;
 out:
 	return ret;
diff --git a/drivers/staging/zram/xvmalloc.c b/drivers/staging/zram/xvmalloc.c
index 1f9c508..93ba8e9 100644
--- a/drivers/staging/zram/xvmalloc.c
+++ b/drivers/staging/zram/xvmalloc.c
@@ -56,17 +56,17 @@ static void clear_flag(struct block_header *block, enum blockflags flag)
  * This is called from xv_malloc/xv_free path, so it
  * needs to be fast.
  */
-static void *get_ptr_atomic(struct page *page, u16 offset, enum km_type type)
+static void *get_ptr_atomic(struct page *page, u16 offset)
 {
 	unsigned char *base;
 
-	base = kmap_atomic(page, type);
+	base = kmap_atomic(page);
 	return base + offset;
 }
 
-static void put_ptr_atomic(void *ptr, enum km_type type)
+static void put_ptr_atomic(void *ptr)
 {
-	kunmap_atomic(ptr, type);
+	kunmap_atomic(ptr);
 }
 
 static u32 get_blockprev(struct block_header *block)
@@ -202,10 +202,10 @@ static void insert_block(struct xv_pool *pool, struct page *page, u32 offset,
 
 	if (block->link.next_page) {
 		nextblock = get_ptr_atomic(block->link.next_page,
-					block->link.next_offset, KM_USER1);
+					block->link.next_offset);
 		nextblock->link.prev_page = page;
 		nextblock->link.prev_offset = offset;
-		put_ptr_atomic(nextblock, KM_USER1);
+		put_ptr_atomic(nextblock);
 		/* If there was a next page then the free bits are set. */
 		return;
 	}
@@ -225,18 +225,18 @@ static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
 
 	if (block->link.prev_page) {
 		tmpblock = get_ptr_atomic(block->link.prev_page,
-				block->link.prev_offset, KM_USER1);
+				block->link.prev_offset);
 		tmpblock->link.next_page = block->link.next_page;
 		tmpblock->link.next_offset = block->link.next_offset;
-		put_ptr_atomic(tmpblock, KM_USER1);
+		put_ptr_atomic(tmpblock);
 	}
 
 	if (block->link.next_page) {
 		tmpblock = get_ptr_atomic(block->link.next_page,
-				block->link.next_offset, KM_USER1);
+				block->link.next_offset);
 		tmpblock->link.prev_page = block->link.prev_page;
 		tmpblock->link.prev_offset = block->link.prev_offset;
-		put_ptr_atomic(tmpblock, KM_USER1);
+		put_ptr_atomic(tmpblock);
 	}
 
 	/* Is this block is at the head of the freelist? */
@@ -249,11 +249,10 @@ static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
 		if (pool->freelist[slindex].page) {
 			struct block_header *tmpblock;
 			tmpblock = get_ptr_atomic(pool->freelist[slindex].page,
-					pool->freelist[slindex].offset,
-					KM_USER1);
+					pool->freelist[slindex].offset);
 			tmpblock->link.prev_page = NULL;
 			tmpblock->link.prev_offset = 0;
-			put_ptr_atomic(tmpblock, KM_USER1);
+			put_ptr_atomic(tmpblock);
 		} else {
 			/* This freelist bucket is empty */
 			__clear_bit(slindex % BITS_PER_LONG,
@@ -284,7 +283,7 @@ static int grow_pool(struct xv_pool *pool, gfp_t flags)
 	stat_inc(&pool->total_pages);
 
 	spin_lock(&pool->lock);
-	block = get_ptr_atomic(page, 0, KM_USER0);
+	block = get_ptr_atomic(page, 0);
 
 	block->size = PAGE_SIZE - XV_ALIGN;
 	set_flag(block, BLOCK_FREE);
@@ -293,7 +292,7 @@ static int grow_pool(struct xv_pool *pool, gfp_t flags)
 
 	insert_block(pool, page, 0, block);
 
-	put_ptr_atomic(block, KM_USER0);
+	put_ptr_atomic(block);
 	spin_unlock(&pool->lock);
 
 	return 0;
@@ -375,7 +374,7 @@ int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
 		return -ENOMEM;
 	}
 
-	block = get_ptr_atomic(*page, *offset, KM_USER0);
+	block = get_ptr_atomic(*page, *offset);
 
 	remove_block(pool, *page, *offset, block, index);
 
@@ -405,7 +404,7 @@ int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
 	block->size = origsize;
 	clear_flag(block, BLOCK_FREE);
 
-	put_ptr_atomic(block, KM_USER0);
+	put_ptr_atomic(block);
 	spin_unlock(&pool->lock);
 
 	*offset += XV_ALIGN;
@@ -426,7 +425,7 @@ void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
 
 	spin_lock(&pool->lock);
 
-	page_start = get_ptr_atomic(page, 0, KM_USER0);
+	page_start = get_ptr_atomic(page, 0);
 	block = (struct block_header *)((char *)page_start + offset);
 
 	/* Catch double free bugs */
@@ -468,7 +467,7 @@ void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
 
 	/* No used objects in this page. Free it. */
 	if (block->size == PAGE_SIZE - XV_ALIGN) {
-		put_ptr_atomic(page_start, KM_USER0);
+		put_ptr_atomic(page_start);
 		spin_unlock(&pool->lock);
 
 		__free_page(page);
@@ -486,7 +485,7 @@ void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
 		set_blockprev(tmpblock, offset);
 	}
 
-	put_ptr_atomic(page_start, KM_USER0);
+	put_ptr_atomic(page_start);
 	spin_unlock(&pool->lock);
 }
 EXPORT_SYMBOL_GPL(xv_free);
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 2a2a92d..1cf68ad 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -161,9 +161,9 @@ static void zram_free_page(struct zram *zram, size_t index)
 		goto out;
 	}
 
-	obj = kmap_atomic(page, KM_USER0) + offset;
+	obj = kmap_atomic(page) + offset;
 	clen = xv_get_object_size(obj) - sizeof(struct zobj_header);
-	kunmap_atomic(obj, KM_USER0);
+	kunmap_atomic(obj);
 
 	xv_free(zram->mem_pool, page, offset);
 	if (clen <= PAGE_SIZE / 2)
@@ -182,9 +182,9 @@ static void handle_zero_page(struct bio_vec *bvec)
 	struct page *page = bvec->bv_page;
 	void *user_mem;
 
-	user_mem = kmap_atomic(page, KM_USER0);
+	user_mem = kmap_atomic(page);
 	memset(user_mem + bvec->bv_offset, 0, bvec->bv_len);
-	kunmap_atomic(user_mem, KM_USER0);
+	kunmap_atomic(user_mem);
 
 	flush_dcache_page(page);
 }
@@ -195,12 +195,12 @@ static void handle_uncompressed_page(struct zram *zram, struct bio_vec *bvec,
 	struct page *page = bvec->bv_page;
 	unsigned char *user_mem, *cmem;
 
-	user_mem = kmap_atomic(page, KM_USER0);
-	cmem = kmap_atomic(zram->table[index].page, KM_USER1);
+	user_mem = kmap_atomic(page);
+	cmem = kmap_atomic(zram->table[index].page);
 
 	memcpy(user_mem + bvec->bv_offset, cmem + offset, bvec->bv_len);
-	kunmap_atomic(cmem, KM_USER1);
-	kunmap_atomic(user_mem, KM_USER0);
+	kunmap_atomic(cmem);
+	kunmap_atomic(user_mem);
 
 	flush_dcache_page(page);
 }
@@ -249,12 +249,12 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 		}
 	}
 
-	user_mem = kmap_atomic(page, KM_USER0);
+	user_mem = kmap_atomic(page);
 	if (!is_partial_io(bvec))
 		uncmem = user_mem;
 	clen = PAGE_SIZE;
 
-	cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+	cmem = kmap_atomic(zram->table[index].page) +
 		zram->table[index].offset;
 
 	ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
@@ -267,8 +267,8 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 		kfree(uncmem);
 	}
 
-	kunmap_atomic(cmem, KM_USER1);
-	kunmap_atomic(user_mem, KM_USER0);
+	kunmap_atomic(cmem);
+	kunmap_atomic(user_mem);
 
 	/* Should NEVER happen. Return bio error if it does. */
 	if (unlikely(ret != LZO_E_OK)) {
@@ -295,20 +295,20 @@ static int zram_read_before_write(struct zram *zram, char *mem, u32 index)
 		return 0;
 	}
 
-	cmem = kmap_atomic(zram->table[index].page, KM_USER0) +
+	cmem = kmap_atomic(zram->table[index].page) +
 		zram->table[index].offset;
 
 	/* Page is stored uncompressed since it's incompressible */
 	if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED))) {
 		memcpy(mem, cmem, PAGE_SIZE);
-		kunmap_atomic(cmem, KM_USER0);
+		kunmap_atomic(cmem);
 		return 0;
 	}
 
 	ret = lzo1x_decompress_safe(cmem + sizeof(*zheader),
 				    xv_get_object_size(cmem) - sizeof(*zheader),
 				    mem, &clen);
-	kunmap_atomic(cmem, KM_USER0);
+	kunmap_atomic(cmem);
 
 	/* Should NEVER happen. Return bio error if it does. */
 	if (unlikely(ret != LZO_E_OK)) {
@@ -359,7 +359,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 	    zram_test_flag(zram, index, ZRAM_ZERO))
 		zram_free_page(zram, index);
 
-	user_mem = kmap_atomic(page, KM_USER0);
+	user_mem = kmap_atomic(page);
 
 	if (is_partial_io(bvec))
 		memcpy(uncmem + offset, user_mem + bvec->bv_offset,
@@ -368,7 +368,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		uncmem = user_mem;
 
 	if (page_zero_filled(uncmem)) {
-		kunmap_atomic(user_mem, KM_USER0);
+		kunmap_atomic(user_mem);
 		if (is_partial_io(bvec))
 			kfree(uncmem);
 		zram_stat_inc(&zram->stats.pages_zero);
@@ -380,7 +380,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
 			       zram->compress_workmem);
 
-	kunmap_atomic(user_mem, KM_USER0);
+	kunmap_atomic(user_mem);
 	if (is_partial_io(bvec))
 			kfree(uncmem);
 
@@ -408,7 +408,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 		zram_set_flag(zram, index, ZRAM_UNCOMPRESSED);
 		zram_stat_inc(&zram->stats.pages_expand);
 		zram->table[index].page = page_store;
-		src = kmap_atomic(page, KM_USER0);
+		src = kmap_atomic(page);
 		goto memstore;
 	}
 
@@ -424,7 +424,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 memstore:
 	zram->table[index].offset = store_offset;
 
-	cmem = kmap_atomic(zram->table[index].page, KM_USER1) +
+	cmem = kmap_atomic(zram->table[index].page) +
 		zram->table[index].offset;
 
 #if 0
@@ -438,9 +438,9 @@ memstore:
 
 	memcpy(cmem, src, clen);
 
-	kunmap_atomic(cmem, KM_USER1);
+	kunmap_atomic(cmem);
 	if (unlikely(zram_test_flag(zram, index, ZRAM_UNCOMPRESSED)))
-		kunmap_atomic(src, KM_USER0);
+		kunmap_atomic(src);
 
 	/* Update stats */
 	zram_stat64_add(zram, &zram->stats.compr_size, clen);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index d3ddd13..184f4f86 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2341,7 +2341,7 @@ static void transport_xor_callback(struct se_cmd *cmd)
 
 	offset = 0;
 	for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
-		addr = kmap_atomic(sg_page(sg), KM_USER0);
+		addr = kmap_atomic(sg_page(sg));
 		if (!addr)
 			goto out;
 
@@ -2349,7 +2349,7 @@ static void transport_xor_callback(struct se_cmd *cmd)
 			*(addr + sg->offset + i) ^= *(buf + offset + i);
 
 		offset += sg->length;
-		kunmap_atomic(addr, KM_USER0);
+		kunmap_atomic(addr);
 	}
 
 out:
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index d8cabc2..2b693ee 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -146,14 +146,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
 					PAGE_SIZE << compound_order(page);
 		} else {
 			BUG_ON(!page);
-			from = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
-					   KM_SOFTIRQ0);
+			from = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
 			page_addr = from;
 			from += mem_off & ~PAGE_MASK;
 			tlen = min(tlen, (size_t)(PAGE_SIZE -
 						(mem_off & ~PAGE_MASK)));
 			memcpy(to, from, tlen);
-			kunmap_atomic(page_addr, KM_SOFTIRQ0);
+			kunmap_atomic(page_addr);
 			to += tlen;
 		}
 
@@ -291,14 +290,13 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
 
 		tlen = min(mem_len, frame_len);
 
-		to = kmap_atomic(page + (mem_off >> PAGE_SHIFT),
-				 KM_SOFTIRQ0);
+		to = kmap_atomic(page + (mem_off >> PAGE_SHIFT));
 		page_addr = to;
 		to += mem_off & ~PAGE_MASK;
 		tlen = min(tlen, (size_t)(PAGE_SIZE -
 					  (mem_off & ~PAGE_MASK)));
 		memcpy(to, from, tlen);
-		kunmap_atomic(page_addr, KM_SOFTIRQ0);
+		kunmap_atomic(page_addr);
 
 		from += tlen;
 		frame_len -= tlen;
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index d9b6a03..da97dce 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -37,9 +37,6 @@ static int emi26_set_reset(struct usb_device *dev, unsigned char reset_bit);
 static int emi26_load_firmware (struct usb_device *dev);
 static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void emi26_disconnect(struct usb_interface *intf);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
 
 /* thanks to drivers/usb/serial/keyspan_pda.c code */
 static int emi26_writememory (struct usb_device *dev, int address,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 9f39062..4e0f167 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -46,9 +46,6 @@ static int emi62_set_reset(struct usb_device *dev, unsigned char reset_bit);
 static int emi62_load_firmware (struct usb_device *dev);
 static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void emi62_disconnect(struct usb_interface *intf);
-static int __init emi62_init (void);
-static void __exit emi62_exit (void);
-
 
 /* thanks to drivers/usb/serial/keyspan_pda.c code */
 static int emi62_writememory(struct usb_device *dev, int address,
diff --git a/drivers/uwb/allocator.c b/drivers/uwb/allocator.c
index e45e673..6e3e713 100644
--- a/drivers/uwb/allocator.c
+++ b/drivers/uwb/allocator.c
@@ -334,10 +334,8 @@ int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *availab
 
 
 	/* fill the not available vector from the available bm */
-	for (bit_index = 0; bit_index < UWB_NUM_MAS; bit_index++) {
-		if (!test_bit(bit_index, available->bm))
-			ai->bm[bit_index] = UWB_RSV_MAS_NOT_AVAIL;
-	}
+	for_each_clear_bit(bit_index, available->bm, UWB_NUM_MAS)
+		ai->bm[bit_index] = UWB_RSV_MAS_NOT_AVAIL;
 
 	if (ai->max_interval == 1) {
 		get_row_descriptors(ai);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c14c42b..bdb2d64 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -937,9 +937,9 @@ static int set_bit_to_user(int nr, void __user *addr)
 	if (r < 0)
 		return r;
 	BUG_ON(r != 1);
-	base = kmap_atomic(page, KM_USER0);
+	base = kmap_atomic(page);
 	set_bit(bit, base);
-	kunmap_atomic(base, KM_USER0);
+	kunmap_atomic(base);
 	set_page_dirty_lock(page);
 	put_page(page);
 	return 0;
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 66bc74d..550dbf0 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -146,7 +146,7 @@ static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
 
 	ret = adp8860_read(client, reg, &reg_val);
 
-	if (!ret && ((reg_val & bit_mask) == 0)) {
+	if (!ret && ((reg_val & bit_mask) != bit_mask)) {
 		reg_val |= bit_mask;
 		ret = adp8860_write(client, reg, reg_val);
 	}
@@ -819,17 +819,7 @@ static struct i2c_driver adp8860_driver = {
 	.id_table = adp8860_id,
 };
 
-static int __init adp8860_init(void)
-{
-	return i2c_add_driver(&adp8860_driver);
-}
-module_init(adp8860_init);
-
-static void __exit adp8860_exit(void)
-{
-	i2c_del_driver(&adp8860_driver);
-}
-module_exit(adp8860_exit);
+module_i2c_driver(adp8860_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 6c68a68..9be58c6 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -160,7 +160,7 @@ static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask
 
 	ret = adp8870_read(client, reg, &reg_val);
 
-	if (!ret && ((reg_val & bit_mask) == 0)) {
+	if (!ret && ((reg_val & bit_mask) != bit_mask)) {
 		reg_val |= bit_mask;
 		ret = adp8870_write(client, reg, reg_val);
 	}
@@ -991,17 +991,7 @@ static struct i2c_driver adp8870_driver = {
 	.id_table = adp8870_id,
 };
 
-static int __init adp8870_init(void)
-{
-	return i2c_add_driver(&adp8870_driver);
-}
-module_init(adp8870_init);
-
-static void __exit adp8870_exit(void)
-{
-	i2c_del_driver(&adp8870_driver);
-}
-module_exit(adp8870_exit);
+module_i2c_driver(adp8870_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c
index 7838a23..7bdadc7 100644
--- a/drivers/video/backlight/ams369fg06.c
+++ b/drivers/video/backlight/ams369fg06.c
@@ -629,18 +629,7 @@ static struct spi_driver ams369fg06_driver = {
 	.resume		= ams369fg06_resume,
 };
 
-static int __init ams369fg06_init(void)
-{
-	return spi_register_driver(&ams369fg06_driver);
-}
-
-static void __exit ams369fg06_exit(void)
-{
-	spi_unregister_driver(&ams369fg06_driver);
-}
-
-module_init(ams369fg06_init);
-module_exit(ams369fg06_exit);
+module_spi_driver(ams369fg06_driver);
 
 MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
 MODULE_DESCRIPTION("ams369fg06 LCD Driver");
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index c6533ba..6dab13f 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -629,17 +629,7 @@ static struct spi_driver corgi_lcd_driver = {
 	.resume		= corgi_lcd_resume,
 };
 
-static int __init corgi_lcd_init(void)
-{
-	return spi_register_driver(&corgi_lcd_driver);
-}
-module_init(corgi_lcd_init);
-
-static void __exit corgi_lcd_exit(void)
-{
-	spi_unregister_driver(&corgi_lcd_driver);
-}
-module_exit(corgi_lcd_exit);
+module_spi_driver(corgi_lcd_driver);
 
 MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00");
 MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c
index 4f5d1c4..6022b67 100644
--- a/drivers/video/backlight/l4f00242t03.c
+++ b/drivers/video/backlight/l4f00242t03.c
@@ -190,6 +190,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
 
 	priv->io_reg = regulator_get(&spi->dev, "vdd");
 	if (IS_ERR(priv->io_reg)) {
+		ret = PTR_ERR(priv->io_reg);
 		dev_err(&spi->dev, "%s: Unable to get the IO regulator\n",
 		       __func__);
 		goto err3;
@@ -197,6 +198,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi)
 
 	priv->core_reg = regulator_get(&spi->dev, "vcore");
 	if (IS_ERR(priv->core_reg)) {
+		ret = PTR_ERR(priv->core_reg);
 		dev_err(&spi->dev, "%s: Unable to get the core regulator\n",
 		       __func__);
 		goto err4;
@@ -272,18 +274,7 @@ static struct spi_driver l4f00242t03_driver = {
 	.shutdown	= l4f00242t03_shutdown,
 };
 
-static __init int l4f00242t03_init(void)
-{
-	return spi_register_driver(&l4f00242t03_driver);
-}
-
-static __exit void l4f00242t03_exit(void)
-{
-	spi_unregister_driver(&l4f00242t03_driver);
-}
-
-module_init(l4f00242t03_init);
-module_exit(l4f00242t03_exit);
+module_spi_driver(l4f00242t03_driver);
 
 MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
 MODULE_DESCRIPTION("EPSON L4F00242T03 LCD");
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
index 78dafc0..efd352b 100644
--- a/drivers/video/backlight/ld9040.c
+++ b/drivers/video/backlight/ld9040.c
@@ -856,18 +856,7 @@ static struct spi_driver ld9040_driver = {
 	.resume		= ld9040_resume,
 };
 
-static int __init ld9040_init(void)
-{
-	return spi_register_driver(&ld9040_driver);
-}
-
-static void __exit ld9040_exit(void)
-{
-	spi_unregister_driver(&ld9040_driver);
-}
-
-module_init(ld9040_init);
-module_exit(ld9040_exit);
+module_spi_driver(ld9040_driver);
 
 MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
 MODULE_DESCRIPTION("ld9040 LCD Driver");
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c
index 4ec78cf..4161f9e 100644
--- a/drivers/video/backlight/lms283gf05.c
+++ b/drivers/video/backlight/lms283gf05.c
@@ -226,18 +226,7 @@ static struct spi_driver lms283gf05_driver = {
 	.remove		= __devexit_p(lms283gf05_remove),
 };
 
-static __init int lms283gf05_init(void)
-{
-	return spi_register_driver(&lms283gf05_driver);
-}
-
-static __exit void lms283gf05_exit(void)
-{
-	spi_unregister_driver(&lms283gf05_driver);
-}
-
-module_init(lms283gf05_init);
-module_exit(lms283gf05_exit);
+module_spi_driver(lms283gf05_driver);
 
 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 MODULE_DESCRIPTION("LCD283GF05 LCD");
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c
index cca43c0..333949f 100644
--- a/drivers/video/backlight/ltv350qv.c
+++ b/drivers/video/backlight/ltv350qv.c
@@ -321,17 +321,7 @@ static struct spi_driver ltv350qv_driver = {
 	.resume		= ltv350qv_resume,
 };
 
-static int __init ltv350qv_init(void)
-{
-	return spi_register_driver(&ltv350qv_driver);
-}
-
-static void __exit ltv350qv_exit(void)
-{
-	spi_unregister_driver(&ltv350qv_driver);
-}
-module_init(ltv350qv_init);
-module_exit(ltv350qv_exit);
+module_spi_driver(ltv350qv_driver);
 
 MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
 MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver");
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index e132157..9b0092e 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -909,18 +909,7 @@ static struct spi_driver s6e63m0_driver = {
 	.resume		= s6e63m0_resume,
 };
 
-static int __init s6e63m0_init(void)
-{
-	return spi_register_driver(&s6e63m0_driver);
-}
-
-static void __exit s6e63m0_exit(void)
-{
-	spi_unregister_driver(&s6e63m0_driver);
-}
-
-module_init(s6e63m0_init);
-module_exit(s6e63m0_exit);
+module_spi_driver(s6e63m0_driver);
 
 MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
 MODULE_DESCRIPTION("S6E63M0 LCD Driver");
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c
index 1997e12..2368b8e 100644
--- a/drivers/video/backlight/tdo24m.c
+++ b/drivers/video/backlight/tdo24m.c
@@ -459,17 +459,7 @@ static struct spi_driver tdo24m_driver = {
 	.resume		= tdo24m_resume,
 };
 
-static int __init tdo24m_init(void)
-{
-	return spi_register_driver(&tdo24m_driver);
-}
-module_init(tdo24m_init);
-
-static void __exit tdo24m_exit(void)
-{
-	spi_unregister_driver(&tdo24m_driver);
-}
-module_exit(tdo24m_exit);
+module_spi_driver(tdo24m_driver);
 
 MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
 MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel");
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 425a736..2b241ab 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -181,18 +181,7 @@ static struct i2c_driver tosa_bl_driver = {
 	.id_table	= tosa_bl_id,
 };
 
-static int __init tosa_bl_init(void)
-{
-	return i2c_add_driver(&tosa_bl_driver);
-}
-
-static void __exit tosa_bl_exit(void)
-{
-	i2c_del_driver(&tosa_bl_driver);
-}
-
-module_init(tosa_bl_init);
-module_exit(tosa_bl_exit);
+module_i2c_driver(tosa_bl_driver);
 
 MODULE_AUTHOR("Dmitry Baryshkov");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 772f601..a2161f6 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -285,18 +285,7 @@ static struct spi_driver tosa_lcd_driver = {
 	.resume		= tosa_lcd_resume,
 };
 
-static int __init tosa_lcd_init(void)
-{
-	return spi_register_driver(&tosa_lcd_driver);
-}
-
-static void __exit tosa_lcd_exit(void)
-{
-	spi_unregister_driver(&tosa_lcd_driver);
-}
-
-module_init(tosa_lcd_init);
-module_exit(tosa_lcd_exit);
+module_spi_driver(tosa_lcd_driver);
 
 MODULE_AUTHOR("Dmitry Baryshkov");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c
index b49063c..b617fae 100644
--- a/drivers/video/backlight/vgg2432a4.c
+++ b/drivers/video/backlight/vgg2432a4.c
@@ -262,20 +262,7 @@ static struct spi_driver vgg2432a4_driver = {
 	.resume		= vgg2432a4_resume,
 };
 
-/* Device driver initialisation */
-
-static int __init vgg2432a4_init(void)
-{
-	return spi_register_driver(&vgg2432a4_driver);
-}
-
-static void __exit vgg2432a4_exit(void)
-{
-	spi_unregister_driver(&vgg2432a4_driver);
-}
-
-module_init(vgg2432a4_init);
-module_exit(vgg2432a4_exit);
+module_spi_driver(vgg2432a4_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
 MODULE_DESCRIPTION("VGG2432A4 LCD Driver");
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 1b0e3dd..63d7b58 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -300,11 +300,7 @@ static int __devinit dw_wdt_drv_probe(struct platform_device *pdev)
 	if (!mem)
 		return -EINVAL;
 
-	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
-				     "dw_wdt"))
-		return -ENOMEM;
-
-	dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem);
 	if (!dw_wdt.regs)
 		return -ENOMEM;
 
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 8464ea1..3df9e09 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -231,7 +231,7 @@ static int __devinit cru_detect(unsigned long map_entry,
 
 	cmn_regs.u1.reax = CRU_BIOS_SIGNATURE_VALUE;
 
-	set_memory_x((unsigned long)bios32_entrypoint, (2 * PAGE_SIZE));
+	set_memory_x((unsigned long)bios32_entrypoint & PAGE_MASK, 2);
 	asminline_call(&cmn_regs, bios32_entrypoint);
 
 	if (cmn_regs.u1.ral != 0) {
@@ -250,7 +250,8 @@ static int __devinit cru_detect(unsigned long map_entry,
 			cru_rom_addr =
 				ioremap(cru_physical_address, cru_length);
 			if (cru_rom_addr) {
-				set_memory_x((unsigned long)cru_rom_addr, cru_length);
+				set_memory_x((unsigned long)cru_rom_addr &
+					PAGE_MASK, cru_length >> PAGE_SHIFT);
 				retval = 0;
 			}
 		}
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index b8ef2c6..c44c333 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -247,7 +247,6 @@ static struct miscdevice imx2_wdt_miscdev = {
 static int __init imx2_wdt_probe(struct platform_device *pdev)
 {
 	int ret;
-	int res_size;
 	struct resource *res;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -256,15 +255,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	res_size = resource_size(res);
-	if (!devm_request_mem_region(&pdev->dev, 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;
-	}
-
-	imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size);
+	imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res);
 	if (!imx2_wdt.base) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		return -ENOMEM;
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index d3a63be..9c8b10c 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -16,7 +16,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <lantiq.h>
+#include <lantiq_soc.h>
 
 /* Section 3.4 of the datasheet
  * The password sequence protects the WDT control register from unintended
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
index 50359ba..529085b 100644
--- a/drivers/watchdog/nuc900_wdt.c
+++ b/drivers/watchdog/nuc900_wdt.c
@@ -72,7 +72,7 @@ struct nuc900_wdt {
 };
 
 static unsigned long nuc900wdt_busy;
-struct nuc900_wdt *nuc900_wdt;
+static struct nuc900_wdt *nuc900_wdt;
 
 static inline void nuc900_wdt_keepalive(void)
 {
@@ -287,7 +287,8 @@ static int __devinit nuc900wdt_probe(struct platform_device *pdev)
 
 	setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0);
 
-	if (misc_register(&nuc900wdt_miscdev)) {
+	ret = misc_register(&nuc900wdt_miscdev);
+	if (ret) {
 		dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n",
 			WATCHDOG_MINOR, ret);
 		goto err_clk;
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 4b33e3f..d19ff51 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -339,6 +339,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
 	return 0;
 
 err_misc:
+	pm_runtime_disable(wdev->dev);
 	platform_set_drvdata(pdev, NULL);
 	iounmap(wdev->base);
 
@@ -371,6 +372,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
+	pm_runtime_disable(wdev->dev);
 	if (!res)
 		return -ENOENT;
 
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index 026b4bb..8b24b00 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -233,7 +233,7 @@ static void __devexit wdt_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
-DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
+static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c
index 42e940c..c3c3188 100644
--- a/drivers/watchdog/wafer5823wdt.c
+++ b/drivers/watchdog/wafer5823wdt.c
@@ -152,12 +152,12 @@ static long wafwdt_ioctl(struct file *file, unsigned int cmd,
 			return -EFAULT;
 
 		if (options & WDIOS_DISABLECARD) {
-			wafwdt_start();
+			wafwdt_stop();
 			retval = 0;
 		}
 
 		if (options & WDIOS_ENABLECARD) {
-			wafwdt_stop();
+			wafwdt_start();
 			retval = 0;
 		}
 
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 909c786..5d7113c 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -212,10 +212,10 @@ static long wm8350_wdt_ioctl(struct file *file, unsigned int cmd,
 
 		/* Setting both simultaneously means at least one must fail */
 		if (options == WDIOS_DISABLECARD)
-			ret = wm8350_wdt_start(wm8350);
+			ret = wm8350_wdt_stop(wm8350);
 
 		if (options == WDIOS_ENABLECARD)
-			ret = wm8350_wdt_stop(wm8350);
+			ret = wm8350_wdt_start(wm8350);
 		break;
 	}
 
diff --git a/drivers/xshm/Kconfig b/drivers/xshm/Kconfig
new file mode 100644
index 0000000..0993346
--- /dev/null
+++ b/drivers/xshm/Kconfig
@@ -0,0 +1,61 @@
+#
+# XSHM Framework
+#
+
+config XSHM
+	tristate
+	default n
+	depends on EXPERIMENTAL
+
+if XSHM && NET
+
+menu "XSHM drivers and interfaces"
+
+config DUMMY_C2C
+	tristate "Dummy C2C GENIO driver"
+	depends on !C2C
+	default XSHM
+	---help---
+	Say "Y" or "M" if you want to compile a dummy C2C driver.
+	Use this if you want to compile without the real
+	C2C driver available.
+
+config XSHM_BUS
+	tristate
+	default XSHM_DEV
+
+config XSHM_BOOT
+	tristate
+	depends on XSHM_DEV
+	default XSHM_DEV
+
+config XSHM_DEV
+	tristate "XSHM Channels for External Shared Memory (XSHM)"
+	depends on DUMMY_C2C || C2C
+	select XSHM_BUS
+	select XSHM_BOOT
+	default XSHM
+	---help---
+	Say "Y" to use External Shared Memory (XSHM) IPC mechanism.
+	XSHM is an IPC protocol used to talk to external device such
+	as modem over a shared memory (e.g. Chip to Chip).
+	Only say "M" here if you want to test XSHM and need to load
+	and unload its module.
+	If unsure say N.
+
+config XSHM_CHR
+	tristate "Character device for External Shared Memory (XSHM)"
+	depends on XSHM_DEV
+	default XSHM_DEV
+	---help---
+	Say "Y" to use a character device for the External Shared
+	Memory (XSHM) IPC mechanism. XSHM is an IPC protocol used to
+	talk to external device such as modem over a shared memory
+	(e.g. Chip to Chip).
+	Only say "M" here if you want to test XSHM and need to load
+	and unload its module.
+	If unsure say N.
+
+endmenu
+
+endif
diff --git a/drivers/xshm/Makefile b/drivers/xshm/Makefile
new file mode 100644
index 0000000..001cd79
--- /dev/null
+++ b/drivers/xshm/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_XSHM_BUS) += xshm_bus.o
+obj-$(CONFIG_XSHM_BOOT) += xshm_boot.o
+obj-$(CONFIG_XSHM_DEV) += xshm_dev.o
+obj-$(CONFIG_XSHM_CHR) +=  xshm_chr.o
+obj-$(CONFIG_DUMMY_C2C) +=  dummy_c2c_genio.o
diff --git a/drivers/xshm/dummy_c2c_genio.c b/drivers/xshm/dummy_c2c_genio.c
new file mode 100644
index 0000000..9b95aa3
--- /dev/null
+++ b/drivers/xshm/dummy_c2c_genio.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author:	Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+/* This is a dummy implementation of GENIO */
+
+#include <linux/module.h>
+#include <linux/c2c_genio.h>
+
+int genio_subscribe(int bit, void (*bit_set_cb)(void *data), void *data)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_subscribe);
+
+int genio_unsubscribe(int bit)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_unsubscribe);
+
+int genio_set_bit(int bit)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_set_bit);
+
+int genio_reset(void)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_reset);
+
+int genio_subscribe_caif_ready(void (*caif_ready_cb) (bool ready))
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_subscribe_caif_ready);
+
+int genio_set_shm_addr(u32 addr, void (*ipc_ready_cb) (void))
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_set_shm_addr);
+
+int genio_bit_alloc(u32 setter_mask, u32 getter_mask)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_bit_alloc);
+
+void genio_register_errhandler(void (*errhandler)(int errno))
+{
+}
+EXPORT_SYMBOL(genio_register_errhandler);
+
+int genio_power_req(int state)
+{
+	return 0;
+}
+EXPORT_SYMBOL(genio_power_req);
+
+static int __init genio_init(void)
+{
+	return 0;
+}
+
+static void __exit genio_exit(void)
+{
+}
+module_init(genio_init);
+module_exit(genio_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xshm/xshm_boot.c b/drivers/xshm/xshm_boot.c
new file mode 100644
index 0000000..5e61d53
--- /dev/null
+++ b/drivers/xshm/xshm_boot.c
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author:	Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": %s :" fmt, __func__
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/crc-ccitt.h>
+#include <linux/kdev_t.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+#include "xshm_ipctoc.h"
+#include <linux/xshm/xshm_dev.h>
+#include <linux/xshm/xshm_netlink.h>
+#include <linux/c2c_genio.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sjur Brændland <sjur.brandeland@stericsson.com>");
+
+#define XSHM_VERSION	0x1
+#define XSHM_SUBVER	0x0
+#define TOC_SZ		512
+#define IMG_MAX_SZ	65536
+#define XSHM_ALIGNMT	sizeof(u32)
+#define XSHM_MIN_CHSZ 3
+#define XSHM_PAYL_ALIGN max(32, L1_CACHE_BYTES)
+#define STE_BOOTIMG_NAME "ste-bootimg.bin"
+
+#define GET_OFFSET(base, ptr) (((u8 *)(ptr)) - ((u8 *)(base)))
+#define OFFS2PTR(base, offs) ((void *) ((u8 *)base + offs))
+#define LEOFFS2PTR(base, offs) ((void *) ((u8 *)base + le32_to_cpu(offs)))
+
+/* Structure use in debug mode for integrity checking */
+struct ipctoc_hash {
+	u16 img_hash;
+	u16 ch_hash;
+	u16 ch_size;
+};
+
+struct xshm_modem {
+	bool config_error;
+	bool commited;
+	bool registered;
+	bool addr_set;
+	u32 modem_bootimg_size;
+	void *shm_start;
+	u32 channels;
+	struct xshm_channel *channel[XSHM_MAX_CHANNELS + 1];
+	struct xshm_ipctoc *ipctoc;
+	bool gennetl_reg;
+};
+
+static unsigned long xshm_start;
+module_param(xshm_start, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xshm_start, "Address for memory shared by host/modem.");
+
+static unsigned long xshm_c2c_bootaddr;
+module_param(xshm_c2c_bootaddr, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xshm_c2c_bootaddr,
+			"Address given to modem (through GENI register)");
+
+static long xshm_size;
+module_param(xshm_size, long, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xshm_size, "Size of SHM area");
+
+#ifdef DEBUG
+
+/* In debug mode we pad around all payload area in order to detect overwrite */
+#define MAGIC_PAD_LEN 32
+#define MAGIC_PAD 0xbc
+
+/* Verify a magic-pad area */
+static inline bool padok(void *mag)
+{
+	u32 *p = mag, v = 0xbcbcbcbc;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		if (*p++ != v)
+			return false;
+	return true;
+}
+
+/* Insert a magic-pad area */
+static inline void add_magic_pad(u32 *offset, void *base)
+{
+	if (*offset < xshm_size)
+		memset(base + *offset, MAGIC_PAD, MAGIC_PAD_LEN);
+	*offset += MAGIC_PAD_LEN;
+}
+
+/* Abuse the pad area to create a checksum of the ipc-toc and descriptors */
+static inline void store_checksum(struct xshm_modem *modem, u32 size)
+{
+	struct ipctoc_hash *hash = (void *)modem->ipctoc;
+	--hash;
+	hash->img_hash =
+		crc_ccitt(0xffff, (u8 *) modem->shm_start,
+				modem->modem_bootimg_size);
+	hash->ch_hash = crc_ccitt(0xffff, (u8 *) modem->ipctoc, size);
+	hash->ch_size = size;
+}
+
+/* Verify that shm config has not been accidently tampered. */
+static inline bool ok_checksum(struct xshm_modem *modem,
+				struct xshm_ipctoc *ipctoc)
+{
+	struct ipctoc_hash *hash = (void *) ipctoc;
+	u16 new_hash, new_imghash;
+	int i;
+	u8 *p;
+
+	if (!modem->commited)
+		return false;
+
+	for (i = 0; i < modem->channels; i++) {
+		struct xshm_ipctoc_channel *ch;
+
+		ch = LEOFFS2PTR(modem->shm_start,
+				ipctoc->channel_offsets[i].rx);
+		p = LEOFFS2PTR(modem->shm_start, ch->ipc);
+		if (!padok(p - MAGIC_PAD_LEN))
+			return false;
+		p = LEOFFS2PTR(modem->shm_start, ch->offset);
+		if (!padok(p - MAGIC_PAD_LEN))
+			return false;
+		ch = LEOFFS2PTR(modem->shm_start,
+				ipctoc->channel_offsets[i].tx);
+		p = LEOFFS2PTR(modem->shm_start, ch->ipc);
+		if (!padok(p - MAGIC_PAD_LEN))
+			return false;
+		p = LEOFFS2PTR(modem->shm_start, ch->offset);
+		if (!padok(p - MAGIC_PAD_LEN))
+			return false;
+	}
+
+	--hash;
+	new_hash = crc_ccitt(0xffff, (u8 *) ipctoc, hash->ch_size);
+	new_imghash =
+		crc_ccitt(0xffff, (u8 *) modem->shm_start,
+				modem->modem_bootimg_size);
+	pr_debug("Hash result:size:%d chksm:%u/%u img:%u/%u\n",
+			hash->ch_size, hash->ch_hash, new_hash,
+			hash->img_hash, new_imghash);
+	return hash->ch_hash == new_hash && hash->img_hash == new_imghash;
+}
+
+static inline void init_data(void *shm_start, u32 offset,
+				int ch, u32 size)
+{
+	memset((u8 *)shm_start + offset, ch + 1, size);
+}
+#else
+#define MAGIC_PAD_LEN 0
+static inline void add_magic_pad(u32 *offset, void *base)
+{
+}
+static inline void store_checksum(struct xshm_modem *modem, u32 size)
+{
+}
+static inline bool ok_checksum(struct xshm_modem *modem, void *ipctoc)
+{
+	return true;
+}
+static inline void init_data(struct xshm_modem *modem, u32 offs, int ch,
+				u32 size)
+{
+}
+#endif
+
+/* write_to_shm - Write SHM Channel descriptors to SHM.
+ *
+ * Based on the configuration data channel configuration
+ * is written to the shared memory area.
+ * This is the data layout:
+ *
+ * +------------+  <---- xshm_start
+ * |	TOC	|
+ * +------------+
+ * | Boot IMG	|
+ * +------------+ <---- rw_start
+ * | RW Data	|
+ * +------------+
+ * | RW Buf idx |
+ * +------------+ <---- ipctoc
+ * | IPC TOC	|
+ * +------------+
+ * | RW Ch Decr |
+ * +------------+ <---- ro_start
+ * | RO Ch Decr |
+ * +------------+
+ * | RO Buf idx |
+ * +------------+
+ * | RO Data	|
+ * +------------+
+ */
+
+static int write_to_shm(struct xshm_modem *modem)
+{
+	int i, pri, bitno;
+	u32 offset, ro_start, rw_start, ipctoc_offs, ipcro_offs;
+	bool found;
+	struct xshm_ipctoc_channel *ch;
+	struct toc_entry *toc_entry;
+	struct xshm_bufidx *bix;
+
+	/*
+	 * Find where to put IPC-TOC by adding up
+	 * the size of Payload buffers pluss buf-indices
+	 */
+	ipctoc_offs = ALIGN(modem->modem_bootimg_size, XSHM_PAYL_ALIGN);
+	rw_start = ipctoc_offs;
+	for (i = 0; i < modem->channels; i++) {
+		int n = modem->channel[i]->tx.buffers;
+		ipctoc_offs += MAGIC_PAD_LEN;
+		ipctoc_offs += offsetof(struct xshm_bufidx, size[n + 2]);
+		ipctoc_offs = ALIGN(ipctoc_offs, XSHM_PAYL_ALIGN);
+		ipctoc_offs += MAGIC_PAD_LEN;
+		ipctoc_offs += modem->channel[i]->tx.ch_size;
+		ipctoc_offs = ALIGN(ipctoc_offs, XSHM_PAYL_ALIGN);
+	}
+	add_magic_pad(&ipctoc_offs, modem->shm_start);
+	pr_debug("IPC toc @ %08x\n", ipctoc_offs);
+
+	/*
+	 * Allocate the IPC-TOC and, initiatlize it.
+	 * The IPC toc will be located after the RW Data and
+	 * buffer indices.
+	 */
+	offset = ipctoc_offs;
+	modem->ipctoc = OFFS2PTR(modem->shm_start, ipctoc_offs);
+	modem->ipctoc->magic[0] = XSHM_IPCTOC_MAGIC1;
+	modem->ipctoc->magic[1] = XSHM_IPCTOC_MAGIC2;
+	modem->ipctoc->version = XSHM_VERSION;
+	modem->ipctoc->subver = XSHM_SUBVER;
+	memset(modem->ipctoc->channel_offsets, 0,
+		sizeof(modem->ipctoc->channel_offsets));
+
+	/* Find start of first channel descriptor */
+	offset += sizeof(struct xshm_ipctoc);
+
+	/*
+	 * Allocate the location for the RW Channel descriptors.
+	 * It will be located after the IPC-TOC.
+	 */
+	offset = ALIGN(offset, XSHM_ALIGNMT);
+	for (i = 0; i < modem->channels; i++) {
+		pr_debug("Channel descriptor %d RW @ 0x%08x\n", i, offset);
+		modem->ipctoc->channel_offsets[i].tx = cpu_to_le32(offset);
+		offset += sizeof(struct xshm_ipctoc_channel);
+		offset = ALIGN(offset, XSHM_ALIGNMT);
+		if (offset > xshm_size)
+			goto badsize;
+	}
+	ro_start = offset;
+
+	/*
+	 * Allocate the location for the RO Channel descriptors.
+	 * It will be located after the RW Channels.
+	 */
+	for (i = 0; i < modem->channels; i++) {
+		pr_debug("Channel descriptor %d RO @ 0x%08x\n", i, offset);
+		modem->ipctoc->channel_offsets[i].rx = cpu_to_le32(offset);
+		offset += sizeof(struct xshm_ipctoc_channel);
+		offset = ALIGN(offset, XSHM_ALIGNMT);
+		if (offset > xshm_size)
+			goto badsize;
+	}
+
+	/*
+	 * Allocate the location for the RO Buffer Indices.
+	 * It will be located after the RO Channels.
+	 */
+	offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+	ipcro_offs = offset;
+	for (i = 0; i < modem->channels; i++) {
+		int n = modem->channel[i]->rx.buffers;
+		ch = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].rx);
+		add_magic_pad(&offset, modem->shm_start);
+		ch->ipc = cpu_to_le32(offset);
+
+		bix = OFFS2PTR(modem->shm_start, offset);
+		bix->read_index = cpu_to_le32(0);
+		bix->write_index = cpu_to_le32(0);
+		bix->state = cpu_to_le32(XSHM_CLOSED);
+		bix->size[0] = cpu_to_le32(0);
+
+		pr_debug("IPC RO[%d] @: 0x%08x\n",  i, offset);
+		offset += offsetof(struct xshm_bufidx, size[n + 2]);
+		offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+		if (offset > xshm_size)
+			goto badsize;
+	}
+
+	/*
+	 * Allocate RO Data Area. This will located after
+	 * the RO Buffer Indices at the end of the Share Memory
+	 * area.
+	 */
+	offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+	for (i = 0; i < modem->channels; i++) {
+		u8 align;
+		u32 size;
+		ch = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].rx);
+		add_magic_pad(&offset, modem->shm_start);
+		ch->offset = cpu_to_le32(offset);
+
+		BUILD_BUG_ON(sizeof(ch->mode) != 1);
+		ch->mode = modem->channel[i]->mode & XSHM_MODE_MASK;
+		ch->buffers = cpu_to_le32(modem->channel[i]->rx.buffers);
+		align = rounddown_pow_of_two(modem->channel[i]->rx.alignment);
+		ch->alignment = align;
+		ch->packets = modem->channel[i]->rx.packets;
+		ch->mtu = modem->channel[i]->rx.mtu;
+		size = modem->channel[i]->tx.ch_size;
+		if (modem->channel[i]->mode & XSHM_PACKET_MODE) {
+			u32 buf_size;
+			buf_size = size / modem->channel[i]->tx.buffers;
+			buf_size = rounddown(buf_size, align);
+			size = buf_size * modem->channel[i]->tx.buffers;
+		}
+		pr_debug("Buffer area RO for Channel[%d] at: 0x%08x size:%d\n",
+				i, offset, size);
+		ch->size = cpu_to_le32(size);
+
+		init_data(modem->shm_start, offset, i,
+				modem->channel[i]->rx.ch_size);
+		offset += modem->channel[i]->rx.ch_size;
+		offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+		if (offset > xshm_size)
+			goto badsize;
+	}
+
+	/*
+	 * Allocate RW Data Area. This will located in the beginning
+	 * just after the Modem Boot Image.
+	 */
+	offset = rw_start;
+	for (i = 0; i < modem->channels; i++) {
+		u8 align;
+		u32 size;
+		ch = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].tx);
+		add_magic_pad(&offset, modem->shm_start);
+		ch->offset = cpu_to_le32(offset);
+		init_data(modem->shm_start, offset, i,
+				modem->channel[i]->tx.ch_size);
+		ch->mode = modem->channel[i]->mode &
+				XSHM_MODE_MASK;
+		ch->buffers = cpu_to_le32(modem->channel[i]->tx.buffers);
+		align = rounddown_pow_of_two(modem->channel[i]->rx.alignment);
+		ch->alignment = align;
+		ch->packets = modem->channel[i]->rx.packets;
+		ch->mtu = modem->channel[i]->rx.mtu;
+		size = modem->channel[i]->tx.ch_size;
+		if (modem->channel[i]->mode & XSHM_PACKET_MODE) {
+			u32 buf_size;
+			buf_size = size / modem->channel[i]->tx.buffers;
+			buf_size = rounddown(buf_size, align);
+			size = buf_size * modem->channel[i]->tx.buffers;
+		}
+		ch->size = cpu_to_le32(size);
+		pr_debug("Buffer area RW for Channel[%d] at: 0x%08x size:%d\n",
+				i, offset, size);
+		offset += modem->channel[i]->tx.ch_size;
+		offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+		if (offset > ro_start)
+			goto badsize;
+	}
+
+	/*
+	 * Allocate RW IPC Area. This will located after RW data area,
+	 * just before the IPC-TOC.
+	 */
+	offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+	for (i = 0; i < modem->channels; i++) {
+		int n = modem->channel[i]->tx.buffers;
+		ch = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].tx);
+		add_magic_pad(&offset, modem->shm_start);
+		ch->ipc = cpu_to_le32(offset);
+		bix = OFFS2PTR(modem->shm_start, offset);
+		bix->read_index = cpu_to_le32(0);
+		bix->write_index = cpu_to_le32(0);
+		bix->state = cpu_to_le32(XSHM_CLOSED);
+		bix->size[0] = cpu_to_le32(0);
+
+		pr_debug("IPC RW[%d] @: 0x%08x\n",  i, offset);
+		offset += offsetof(struct xshm_bufidx, size[n + 2]);
+		offset = ALIGN(offset, XSHM_PAYL_ALIGN);
+		if (offset > xshm_size)
+			goto badsize;
+	}
+
+	/* Allocate genio bits for each channel according to priority*/
+	bitno = 0;
+	for (pri = 0; pri < 8; pri++) {
+		for (i = 0; i < modem->channels; i++) {
+			if (modem->channel[i]->priority == pri) {
+				ch = LEOFFS2PTR(modem->shm_start,
+					modem->ipctoc->channel_offsets[i].tx);
+				ch->write_bit = cpu_to_le16(bitno * 4);
+				ch->read_bit = cpu_to_le16(bitno * 4 + 2);
+				ch = LEOFFS2PTR(modem->shm_start,
+					modem->ipctoc->channel_offsets[i].rx);
+				ch->write_bit = cpu_to_le16(bitno * 4 + 1);
+				ch->read_bit = cpu_to_le16(bitno * 4 + 3);
+				bitno++;
+			}
+		}
+	}
+
+	/*
+	 * The Master TOC points out the boot images for the modem,
+	 * Use the first avilable entry in the toc to write the pointer,
+	 * to the IPC-TOC defined above.
+	 */
+	found = false;
+	for (toc_entry = modem->shm_start, i = 0; i < 16; i++, toc_entry++)
+		if (toc_entry->start == cpu_to_le32(0xffffffff)) {
+			pr_debug("IPCTOC address written into Master TOC"
+					" @ 0x%08x\n", i * 32);
+			toc_entry->start =
+				cpu_to_le32(GET_OFFSET(modem->shm_start,
+							modem->ipctoc));
+			toc_entry->size = cpu_to_le32(0);
+			toc_entry->flags = cpu_to_le32(0);
+			toc_entry->entry_point = cpu_to_le32(0);
+			toc_entry->load_addr = cpu_to_le32(0xffffffff);
+			memset(toc_entry->name, 0, sizeof(toc_entry->name));
+			sprintf(toc_entry->name, "ipc-toc");
+			found = true;
+			break;
+		}
+	if (!found) {
+		pr_debug("Cannot insert IPC-TOC in toc\n");
+		goto bad_config;
+	}
+
+	store_checksum(modem, ipcro_offs - ipctoc_offs);
+
+	return 0;
+
+badsize:
+	pr_debug("IPCTOC not enough space offset (size:0x%lx offset:0x%x\n",
+			xshm_size, offset);
+	return -ENOSPC;
+
+bad_config:
+	pr_debug("IPCTOC bad configuration data\n");
+	return -EINVAL;
+}
+
+static int xshm_verify_config(struct xshm_modem *modem,
+				struct xshm_channel *xcfg)
+{
+	int j;
+
+	if ((xcfg->mode & XSHM_MODE_MASK) != XSHM_PACKET_MODE &&
+			(xcfg->mode & XSHM_MODE_MASK) != XSHM_STREAM_MODE) {
+		pr_debug("Bad config:"
+				"channel mode must be set\n");
+		return -EINVAL;
+	}
+	if (xcfg->mode & XSHM_PACKET_MODE && xcfg->rx.buffers < 2) {
+		pr_debug("Bad config:minimum 2 buffers "
+				"must be set for packet mode\n");
+		return -EINVAL;
+	}
+
+	if (xcfg->rx.ch_size < XSHM_MIN_CHSZ) {
+		pr_debug("Bad config:"
+				"Channel size must be larger than %d\n",
+				XSHM_MIN_CHSZ);
+		return -EINVAL;
+	}
+
+	if (xcfg->mode & XSHM_PACKET_MODE) {
+		if (xcfg->tx.buffers < 2) {
+			pr_debug("Bad config:"
+				"buffers must be minimum 2 packet mode\n");
+			return -EINVAL;
+		}
+		if (xcfg->tx.packets < 1) {
+			pr_debug("Bad config:"
+				"packets must be set for packet mode\n");
+			return -EINVAL;
+		}
+	}
+
+	if (xcfg->tx.ch_size < XSHM_MIN_CHSZ) {
+		pr_debug("Bad config:"
+				"Channel size must be larger than %d\n",
+				XSHM_MIN_CHSZ);
+		return -EINVAL;
+	}
+
+	if (xcfg->name[0] == '\0') {
+		pr_debug("Channel must be named\n");
+		return -EINVAL;
+	}
+	for (j = 0; j < modem->channels; j++) {
+		struct xshm_channel *xcfg2 = modem->channel[j];
+		if (xcfg != xcfg2 && strcmp(xcfg->name, xcfg2->name) == 0) {
+			pr_debug("Channels has same name:%s\n",
+					 xcfg->name);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int verify_config(struct xshm_modem *modem)
+{
+	int i;
+
+	if (modem->channels == 0) {
+		pr_debug("Bad config: minimum one channel must be defined\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < modem->channels; i++) {
+		int err = xshm_verify_config(modem, modem->channel[i]);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * Create Configuration data for the xshm devices.
+ */
+static void create_devs(struct xshm_modem *modem)
+{
+	int i;
+
+	for (i = 0; i < modem->channels; i++) {
+		struct xshm_bufidx *buf_rx, *buf_tx;
+		struct xshm_ipctoc_channel *ch_rx, *ch_tx;
+		struct xshm_channel *xcfg = modem->channel[i];
+		ch_rx = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].rx);
+		buf_rx = LEOFFS2PTR(modem->shm_start, ch_rx->ipc);
+		ch_tx = LEOFFS2PTR(modem->shm_start,
+				modem->ipctoc->channel_offsets[i].tx);
+		buf_tx = LEOFFS2PTR(modem->shm_start, ch_tx->ipc);
+
+		/*
+		 * Due to restricted read-only access
+		 * we swap positions for read/write
+		 * pointers.
+		 */
+		xcfg->tx.write = &buf_tx->write_index;
+		xcfg->tx.read = &buf_rx->read_index;
+
+		xcfg->rx.write = &buf_rx->write_index;
+		xcfg->rx.read = &buf_tx->read_index;
+
+		xcfg->rx.addr = LEOFFS2PTR(modem->shm_start, ch_rx->offset);
+		xcfg->tx.addr = LEOFFS2PTR(modem->shm_start, ch_tx->offset);
+		xcfg->rx.state = &buf_rx->state;
+		xcfg->tx.state = &buf_tx->state;
+		xcfg->tx.buf_size = buf_tx->size;
+		xcfg->rx.buf_size = buf_rx->size;
+
+		xcfg->rx.xfer_bit = le16_to_cpu(ch_rx->write_bit);
+		xcfg->tx.xfer_bit = le16_to_cpu(ch_tx->write_bit);
+		xcfg->rx.xfer_done_bit = le16_to_cpu(ch_rx->read_bit);
+		xcfg->tx.xfer_done_bit = le16_to_cpu(ch_tx->read_bit);
+
+		if (xcfg->mode & XSHM_PAIR_MODE) {
+			struct xshm_channel *pair;
+			pr_debug("Channel[%d] is in PAIR mode\n", i);
+			if (i < 1) {
+				pr_debug("No channel to pair with\n");
+				continue;
+			}
+			/* Cross couple rx/tx on the pair */
+			pair = modem->channel[i - 1];
+
+			/* Copy everything but the kobj which is at the end */
+			memcpy(&xcfg->tx, &pair->rx,
+					offsetof(struct xshm_udchannel, kobj));
+			memcpy(&xcfg->rx, &pair->tx,
+					offsetof(struct xshm_udchannel, kobj));
+		} else if (xcfg->mode & XSHM_LOOP_MODE) {
+			pr_debug("Channel[%d] is in LOOP mode\n", i);
+			/*
+			 * Connect rx/tx in a pair. Copy everything,
+			 * but the kobj which is at the end
+			 */
+			memcpy(&xcfg->tx, &xcfg->rx,
+					offsetof(struct xshm_udchannel, kobj));
+		}
+
+		pr_devel("RX[%d] wi:%p ri:%p\n", i, xcfg->rx.read,
+				xcfg->rx.write);
+		pr_devel("TX[%d] wi:%p ri:%p\n", i, xcfg->tx.read,
+				xcfg->tx.write);
+	}
+}
+
+struct xshm_modem *modem;
+
+struct xshm_modem *get_modem(struct sk_buff *skb, struct genl_info *info)
+{
+	return modem;
+}
+
+static int do_commit(struct xshm_modem *modem)
+{
+	int err;
+
+	if (modem->config_error) {
+		pr_devel("config error detected\n");
+		return -EINVAL;
+	}
+
+	if (modem->commited) {
+		pr_devel("already commited\n");
+		modem->config_error = true;
+		return -EINVAL;
+	}
+	err = verify_config(modem);
+	if (err) {
+		pr_devel("bad config\n");
+		modem->config_error = true;
+		return err;
+	}
+	err = write_to_shm(modem);
+	if (err) {
+		pr_devel("writei to SHM failed\n");
+		modem->config_error = true;
+		return err;
+	}
+	modem->commited = true;
+	create_devs(modem);
+	return 0;
+}
+
+static int do_register(struct xshm_modem *modem)
+{
+	int err;
+
+	if (!modem->commited || modem->registered || modem->config_error) {
+		pr_devel("bad sequence of requests\n");
+		modem->config_error = true;
+		return -EINVAL;
+	}
+
+	err = verify_config(modem);
+	if (err) {
+		modem->config_error = true;
+		pr_devel("bad config\n");
+		return err;
+	}
+	modem->registered = true;
+
+	xshm_register_devices(modem->channel, modem->channels);
+
+	return 0;
+}
+
+static void do_reset(struct xshm_modem *modem)
+{
+	int i;
+
+	xshm_reset();
+	modem->config_error = false;
+	modem->registered = false;
+	modem->commited = false;
+	modem->addr_set = false;
+	modem->modem_bootimg_size = TOC_SZ;
+	for (i = 0; i < modem->channels; i++) {
+		kfree(modem->channel[i]);
+		modem->channel[i] = NULL;
+	}
+	modem->channels = 0;
+}
+
+static int do_set_addr(struct xshm_modem *modem)
+{
+	int err;
+	if (!modem->commited || modem->addr_set || modem->config_error) {
+		pr_devel("bad sequence of requests\n");
+		modem->config_error = true;
+		return -EINVAL;
+	}
+	err = verify_config(modem);
+	if (err) {
+		modem->config_error = true;
+		pr_devel("bad config\n");
+		return err;
+	}
+	modem->addr_set = true;
+	return genio_set_shm_addr(xshm_c2c_bootaddr, genio_ipc_ready_cb);
+}
+
+static int copy_name(const char *src, char *d, size_t count)
+{
+	const char *s, *end = src + count;
+	for (s = src; *s && s < end; s++, d++)
+		if (*s == '\0' || *s == '\n')
+			break;
+		else if (!isalnum(*s)) {
+			pr_debug("Illegal chr:'%c' in name:'%s'\n", *s, src);
+			return -EINVAL;
+		} else if (s - src >= XSHM_NAMESZ - 1) {
+			pr_debug("Name '%s'too long\n", src);
+			return -EINVAL;
+		} else
+			*d = *s;
+	*d = '\0';
+
+	return count;
+}
+
+/* XSHM Generic NETLINK family */
+static struct genl_family xshm_gnl_family = {
+	.id = GENL_ID_GENERATE,
+	.hdrsize = 0,
+	.name = "XSHM",
+	.version = XSHM_PROTO_VERSION,
+	.maxattr = XSHM_A_MAX,
+};
+
+/* XSHM Netlink attribute policy */
+static const struct nla_policy xshm_genl_policy[XSHM_A_MAX + 1] = {
+	[XSHM_A_VERSION] = { .type = NLA_U8 },
+	[XSHM_A_SUB_VERSION] = { .type = NLA_U8 },
+	[__XSHM_A_FLAGS] = { .type = NLA_U32 },
+	[XSHM_A_NAME] = { .type = NLA_NUL_STRING, .len = XSHM_NAMESZ},
+	[XSHM_A_RX_CHANNEL] = { .type = NLA_NESTED },
+	[XSHM_A_TX_CHANNEL] = { .type = NLA_NESTED },
+	[XSHM_A_PRIORITY] = { .type = NLA_U8 },
+	[XSHM_A_LATENCY] = { .type = NLA_U8 },
+};
+
+/* Policy for uni-directional attributes for stream */
+static const struct nla_policy stream_policy[XSHM_A_MAX + 1] = {
+	[XSHM_A_CHANNEL_SIZE] = { .type = NLA_U32 },
+};
+
+/* Policy for uni-directional attributes for packet */
+static const struct nla_policy packet_policy[XSHM_A_MAX + 1] = {
+	[XSHM_A_CHANNEL_SIZE] = { .type = NLA_U32 },
+	[XSHM_A_CHANNEL_BUFFERS] = { .type = NLA_U32 },
+	[XSHM_A_MTU] = { .type = NLA_U16 },
+	[XSHM_A_ALIGNMENT] = { .type = NLA_U8 },
+	[XSHM_A_PACKETS] = { .type = NLA_U8 },
+};
+
+static int xshm_add_udchannel(struct xshm_udchannel *chn, int attr,
+			struct genl_info *info, struct nla_policy const *policy)
+{
+	struct nlattr *nla;
+	int nla_rem;
+
+	if (!info->attrs[attr])
+		return -EINVAL;
+
+	if (nla_validate_nested(info->attrs[attr],
+					XSHM_A_MAX,
+					policy) != 0) {
+		pr_info("Invalid RX channel attributes\n");
+		return -EINVAL;
+	}
+
+	nla_for_each_nested(nla, info->attrs[attr], nla_rem) {
+
+		if (nla_type(nla) == XSHM_A_CHANNEL_SIZE)
+			chn->ch_size = nla_get_u32(nla);
+
+		if (nla_type(nla) == XSHM_A_CHANNEL_BUFFERS)
+			chn->buffers = nla_get_u32(nla);
+
+		if (nla_type(nla) == XSHM_A_MTU)
+			chn->mtu = nla_get_u16(nla);
+
+		if (nla_type(nla) == XSHM_A_PACKETS)
+			chn->packets = nla_get_u8(nla);
+
+		if (nla_type(nla) == XSHM_A_ALIGNMENT) {
+			chn->alignment = nla_get_u8(nla);
+			chn->alignment = rounddown_pow_of_two(chn->alignment);
+		}
+
+	}
+	return 0;
+}
+
+static int xshm_add_channel(struct xshm_channel *cfg, struct genl_info *info,
+			int mode)
+{
+	int len, err;
+	struct nla_policy const *policy;
+	char name[XSHM_NAMESZ];
+
+	policy = (mode == XSHM_PACKET_MODE) ? packet_policy : stream_policy;
+
+	if (info->attrs[XSHM_A_VERSION]) {
+		u8 version;
+		u8 sub_version;
+
+		version = nla_get_u8(info->attrs[XSHM_A_VERSION]);
+		if (!info->attrs[XSHM_A_SUB_VERSION])
+			return -EINVAL;
+		sub_version = nla_get_u8(info->attrs[XSHM_A_SUB_VERSION]);
+		if (version != 1 || sub_version != 0) {
+			pr_info("Bad version or sub_version\n");
+			return -EINVAL;
+		}
+	}
+
+	if (!info->attrs[XSHM_A_NAME]) {
+		pr_debug("Name not specified\n");
+		return -EINVAL;
+	}
+
+	len = nla_strlcpy(name, info->attrs[XSHM_A_NAME],
+			XSHM_NAMESZ);
+
+	if (len > XSHM_NAMESZ)
+		return -EINVAL;
+
+	err = copy_name(name, cfg->name, sizeof(name));
+	if (err < 0)
+		return err;
+
+	cfg->excl_group = 1;
+	if (info->attrs[XSHM_A_EXCL_GROUP])
+		cfg->excl_group = nla_get_u8(info->attrs[XSHM_A_EXCL_GROUP]);
+
+	err = xshm_add_udchannel(&cfg->rx, XSHM_A_RX_CHANNEL, info, policy);
+
+	if (err)
+		return err;
+	err = xshm_add_udchannel(&cfg->tx, XSHM_A_TX_CHANNEL, info, policy);
+
+	if (err)
+		return err;
+
+	if (info->attrs[XSHM_A_PRIORITY]) {
+		cfg->priority = nla_get_u8(info->attrs[XSHM_A_PRIORITY]);
+		/* silently fixup bad value */
+		if (cfg->priority > 7)
+			cfg->priority = 0;
+	}
+
+	if (info->attrs[XSHM_A_LATENCY])
+		cfg->latency = nla_get_u8(info->attrs[XSHM_A_LATENCY]);
+
+	if (info->attrs[__XSHM_A_FLAGS])
+		cfg->mode |= nla_get_u32(info->attrs[__XSHM_A_FLAGS]);
+
+
+	return 0;
+}
+
+static int do_reply(struct genl_info *info, int result)
+{
+	struct sk_buff *msg;
+	int err;
+	void *reply;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (msg == NULL)
+		return -ENOMEM;
+
+	reply = genlmsg_put_reply(msg, info, &xshm_gnl_family, 0, result);
+	if (reply == NULL) {
+		kfree_skb(msg);
+		return -EMSGSIZE;
+	}
+
+	genlmsg_end(msg, reply);
+	err = genlmsg_reply(msg, info);
+	return err;
+}
+
+static int xshm_add_ch(struct sk_buff *skb, struct genl_info *info, int mode)
+{
+	int err;
+	struct xshm_channel *cfg;
+	struct xshm_modem *modem = get_modem(skb, info);
+	if (!modem)
+		return -EINVAL;
+
+	if (modem->channels + 1 > XSHM_MAX_CHANNELS) {
+		pr_debug("Too many channels added\n");
+		return -EINVAL;
+	}
+
+
+	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+	if (cfg == NULL)
+		return -ENOMEM;
+
+	cfg->mode = mode;
+	err = xshm_add_channel(cfg, info, mode);
+	if (err)
+		goto error;
+
+	modem->channel[modem->channels] = cfg;
+	++modem->channels;
+
+	err = xshm_verify_config(modem, cfg);
+	if (err)
+		goto error;
+
+	err = do_reply(info, 0);
+	if (err)
+		goto error;
+	return err;
+
+error:
+	--modem->channels;
+	kfree(cfg);
+	return err;
+}
+
+static int xshm_add_packet_ch(struct sk_buff *skb, struct genl_info *info)
+{
+	return xshm_add_ch(skb, info, XSHM_PACKET_MODE);
+}
+
+static int xshm_add_stream_ch(struct sk_buff *skb, struct genl_info *info)
+{
+	return xshm_add_ch(skb, info, XSHM_STREAM_MODE);
+}
+
+
+static int xshm_c_commit(struct sk_buff *skb, struct genl_info *info)
+{
+	struct xshm_modem *modem = get_modem(skb, info);
+	int err;
+	if (!modem)
+		return -EINVAL;
+
+	err = do_commit(modem);
+	if (!err)
+		do_reply(info, 0);
+	return err;
+}
+
+static int xshm_c_register(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	struct xshm_modem *modem = get_modem(skb, info);
+	if (!modem)
+		return -EINVAL;
+
+	err = do_register(modem);
+	if (!err)
+		do_reply(info, 0);
+	return err;
+}
+
+static int xshm_c_set_addr(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	struct xshm_modem *modem = get_modem(skb, info);
+	if (!modem)
+		return -EINVAL;
+
+	err = do_set_addr(modem);
+	if (!err)
+		do_reply(info, 0);
+	return err;
+}
+
+static int xshm_c_reset(struct sk_buff *skb, struct genl_info *info)
+{
+	struct xshm_modem *modem = get_modem(skb, info);
+	if (!modem)
+		return -EINVAL;
+
+	do_reset(modem);
+	do_reply(info, 0);
+	return 0;
+}
+
+static int xshm_c_verify(struct sk_buff *skb, struct genl_info *info)
+{
+	int err;
+	struct xshm_modem *modem = get_modem(skb, info);
+	if (!modem)
+		return -EINVAL;
+
+	err = verify_config(modem);
+	if (!err)
+		do_reply(info, 0);
+	return err;
+}
+
+static struct genl_ops xshm_genl_ops[] = {
+	{
+	.cmd = XSHM_C_ADD_STREAM_CHANNEL,
+	.flags = GENL_ADMIN_PERM,
+	.policy = xshm_genl_policy,
+	.doit = xshm_add_stream_ch,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = XSHM_C_ADD_PACKET_CHANNEL,
+	.flags = GENL_ADMIN_PERM,
+	.policy = xshm_genl_policy,
+	.doit = xshm_add_packet_ch,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = XSHM_C_COMMIT,
+	.flags = GENL_ADMIN_PERM,
+	.doit = xshm_c_commit,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = XSHM_C_REGISTER,
+	.flags = GENL_ADMIN_PERM,
+	.doit = xshm_c_register,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = XSHM_C_SET_ADDR,
+	.flags = GENL_ADMIN_PERM,
+	.doit = xshm_c_set_addr,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = XSHM_C_RESET,
+	.flags = GENL_ADMIN_PERM,
+	.doit = xshm_c_reset,
+	.dumpit = NULL,
+	},
+	{
+	.cmd = __XSHM_C_VERIFY,
+	.flags = GENL_ADMIN_PERM,
+	.doit = xshm_c_verify,
+	.dumpit = NULL,
+	},
+
+};
+
+
+static void xshm_firmware(const struct firmware *fw, void *context)
+{
+	struct xshm_modem *modem = context;
+
+	if (fw == NULL) {
+		pr_warn("No boot-img provided\n");
+		return;
+	}
+
+	if (modem->commited) {
+		pr_warn("Received firmware too late in modem boot\n");
+		return;
+	}
+
+	pr_debug("recevied firmware\n");
+	memcpy(modem->shm_start, fw->data, fw->size);
+}
+
+/* Initialize boot handling and create sysfs entries*/
+int __init xshm_boot_init(void)
+{
+	int err = -EINVAL;
+	bool xshm_fake = false;
+
+	modem = kzalloc(sizeof(struct xshm_modem), GFP_KERNEL);
+	if (modem == NULL)
+		return -ENOMEM;
+
+	/* Negative xshm_size indicates module test without real SHM */
+	if (xshm_size < 0) {
+		xshm_fake = true;
+		xshm_size = abs(xshm_size);
+	}
+
+	if (xshm_size < TOC_SZ)
+		goto bad_config;
+
+	if (xshm_fake) {
+		modem->shm_start = kzalloc(xshm_size, GFP_KERNEL);
+		err = -ENOMEM;
+		if (!modem->shm_start)
+			goto error;
+		xshm_start = (unsigned long) modem->shm_start;
+		memset(modem->shm_start, 0xaa, xshm_size);
+	} else {
+		if (xshm_start == 0)
+			goto bad_config;
+		modem->shm_start = ioremap(xshm_start, xshm_size);
+	}
+
+	/* Initiate the Master TOC to 0xff for the first 512 bytes */
+	if (xshm_size > TOC_SZ)
+		memset(modem->shm_start, 0xff, TOC_SZ);
+
+	modem->modem_bootimg_size = TOC_SZ;
+
+	pr_debug("Boot image addr: %p size:%d\n", modem->shm_start,
+			modem->modem_bootimg_size);
+
+	err = genl_register_family_with_ops(&xshm_gnl_family,
+		xshm_genl_ops, ARRAY_SIZE(xshm_genl_ops));
+	if (err)
+		goto error;
+
+	modem->gennetl_reg = 1;
+
+	err = xshm_request_firmware(modem, THIS_MODULE,
+			STE_BOOTIMG_NAME, xshm_firmware);
+	if (err)
+		goto error;
+
+	return err;
+error:
+	pr_debug("initialization failed\n");
+
+	if (xshm_fake)
+		kfree(modem->shm_start);
+	return err;
+bad_config:
+	pr_err("Bad module configuration:"
+			" xshm_base_address:%lu xshm_size:%lu err:%d\n",
+			xshm_start, xshm_size, err);
+	/* Buildin module should not return error */
+	return -EINVAL;
+}
+
+void __exit xshm_boot_exit(void)
+{
+
+	if (modem->gennetl_reg)
+		genl_unregister_family(&xshm_gnl_family);
+	modem->gennetl_reg = 0;
+}
+module_init(xshm_boot_init);
+module_exit(xshm_boot_exit);
diff --git a/drivers/xshm/xshm_bus.c b/drivers/xshm/xshm_bus.c
new file mode 100644
index 0000000..d6410a6d
--- /dev/null
+++ b/drivers/xshm/xshm_bus.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/xshm/xshm_dev.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sjur Brændland <sjur.brandeland@stericsson.com>");
+
+static int xshm_dev_match(struct device *_dv, struct device_driver *_dr)
+{
+	struct xshm_dev *dev = container_of(_dv, struct xshm_dev, dev);
+	struct xshm_driver *drv = container_of(_dr, struct xshm_driver, driver);
+
+	return drv->mode ==  (drv->mode & dev->cfg.mode);
+}
+
+static int xshm_dev_probe(struct device *_d)
+{
+	struct xshm_dev *dev = container_of(_d, struct xshm_dev, dev);
+	struct xshm_driver *drv = container_of(dev->dev.driver,
+						 struct xshm_driver, driver);
+	return drv->probe(dev);
+}
+
+static int xshm_dev_remove(struct device *_d)
+{
+	struct xshm_dev *dev = container_of(_d, struct xshm_dev, dev);
+	struct xshm_driver *drv = container_of(dev->dev.driver,
+						 struct xshm_driver, driver);
+	drv->remove(dev);
+	return 0;
+}
+
+static struct bus_type xshm_bus = {
+	.name  = "xshm",
+	.match = xshm_dev_match,
+	.probe = xshm_dev_probe,
+	.remove = xshm_dev_remove,
+};
+
+struct xshm_iter_data {
+	void *data;
+	void (*fn)(struct xshm_dev *, void *);
+};
+
+int xshm_iter(struct device *_dev, void *data)
+{
+	struct xshm_dev *dev = container_of(_dev, struct xshm_dev, dev);
+	struct xshm_iter_data *iter_data = data;
+
+	iter_data->fn(dev, iter_data->data);
+	return 0;
+}
+
+void xshm_foreach_dev(void fn(struct xshm_dev *, void *), void *data)
+{
+	struct xshm_iter_data iter = {
+		.data = data,
+		.fn = fn
+	};
+
+	bus_for_each_dev(&xshm_bus, NULL, &iter, xshm_iter);
+}
+EXPORT_SYMBOL_GPL(xshm_foreach_dev);
+
+int xshm_register_driver(struct xshm_driver *driver)
+{
+	driver->driver.bus = &xshm_bus;
+	return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(xshm_register_driver);
+
+void xshm_unregister_driver(struct xshm_driver *driver)
+{
+	driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(xshm_unregister_driver);
+
+int xshm_register_device(struct xshm_dev *dev)
+{
+	int err;
+
+	dev->dev.bus = &xshm_bus;
+	err = device_register(&dev->dev);
+	return err;
+}
+EXPORT_SYMBOL_GPL(xshm_register_device);
+
+void xshm_unregister_device(struct xshm_dev *dev)
+{
+	device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(xshm_unregister_device);
+
+static int xshm_bus_init(void)
+{
+	if (bus_register(&xshm_bus) != 0)
+		panic("xshm bus registration failed");
+	return 0;
+}
+
+static void __exit xshm_bus_exit(void)
+{
+	bus_unregister(&xshm_bus);
+}
+
+core_initcall(xshm_bus_init);
+module_exit(xshm_bus_exit);
diff --git a/drivers/xshm/xshm_chr.c b/drivers/xshm/xshm_chr.c
new file mode 100644
index 0000000..6951a90
--- /dev/null
+++ b/drivers/xshm/xshm_chr.c
@@ -0,0 +1,1262 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author:	Per Sigmond / Per.Sigmond@stericsson.com
+ *		Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s :" fmt, __func__
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/xshm/xshm_dev.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sjur Brændland <sjur.brandeland@stericsson.com>");
+
+static LIST_HEAD(xshmchr_chrdev_list);
+static spinlock_t list_lock;
+
+#define xdev_dbg(dev, fmt, arg...) \
+		dev_dbg(dev->misc.this_device, pr_fmt(fmt), ##arg)
+
+#define xdev_vdbg(dev, fmt, arg...) \
+		dev_vdbg(dev->misc.this_device, pr_fmt(fmt), ##arg)
+
+#define pr_xchrstate(dev, str, arg...)			\
+	xdev_vdbg(dev, str " State: %s %s\n", ##arg,	\
+		STATE_IS_PENDING(dev) ? "pending" : "", \
+		STATE_IS_OPEN(dev) ? "open" : "close")
+
+#define OPEN_TOUT			(25 * HZ)
+#define CONN_STATE_OPEN_BIT		0
+#define CONN_STATE_PENDING_BIT		1
+#define CONN_REMOTE_TEARDOWN_BIT	2
+#define CONN_EOF_BIT			4
+
+#define STATE_IS_OPEN(dev) test_bit(CONN_STATE_OPEN_BIT, \
+					(void *) &(dev)->conn_state)
+#define STATE_IS_REMOTE_TEARDOWN(dev) test_bit(CONN_REMOTE_TEARDOWN_BIT, \
+					(void *) &(dev)->conn_state)
+#define STATE_IS_PENDING(dev) test_bit(CONN_STATE_PENDING_BIT, \
+					(void *) &(dev)->conn_state)
+#define SET_STATE_OPEN(dev) (set_bit(CONN_STATE_OPEN_BIT,	\
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_STATE_OPEN:%d\n", dev->conn_state))
+#define SET_STATE_CLOSED(dev) (clear_bit(CONN_STATE_OPEN_BIT,	\
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_STATE_CLOSED:%d\n", dev->conn_state))
+#define SET_PENDING_ON(dev) (set_bit(CONN_STATE_PENDING_BIT,	\
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_PENDING_ON:%d\n", dev->conn_state))
+#define SET_PENDING_OFF(dev) (clear_bit(CONN_STATE_PENDING_BIT, \
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_PENDING_OFF:%d\n", dev->conn_state))
+#define SET_REMOTE_TEARDOWN(dev) (set_bit(CONN_REMOTE_TEARDOWN_BIT,	\
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_REMOTE_TEARDOWN:%d\n", dev->conn_state))
+#define CLEAR_REMOTE_TEARDOWN(dev) (clear_bit(CONN_REMOTE_TEARDOWN_BIT, \
+			(void *) &(dev)->conn_state), \
+			pr_devel("CLEAR_REMOTE_TEARDOWN:%d\n", dev->conn_state))
+#define SET_EOF(dev) (set_bit(CONN_EOF_BIT,	\
+			(void *) &(dev)->conn_state), \
+			pr_devel("SET_EOF:%d\n", dev->conn_state))
+#define CLEAR_EOF(dev) (clear_bit(CONN_EOF_BIT, \
+			(void *) &(dev)->conn_state), \
+			pr_devel("CLEAR_EOF:%d\n", dev->conn_state))
+#define STATE_IS_EOF(dev) test_bit(CONN_EOF_BIT, \
+					(void *) &(dev)->conn_state)
+
+#define CHR_READ_FLAG 0x01
+#define CHR_WRITE_FLAG 0x02
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *debugfsdir;
+#include <linux/debugfs.h>
+#define	dbfs_atomic_inc(a) atomic_inc(a)
+#define	dbfs_atomic_add(v, a) atomic_add_return(v, a)
+#else
+#define	dbfs_atomic_inc(a) 0
+#define	dbfs_atomic_add(v, a) 0
+#endif
+
+struct ringbuf {
+	__le32 *ri;	/* Pointer to read-index in shared memory.*/
+	__le32 *wi;	/* Pointer to write-index in shared memory */
+	unsigned int size;/* Size of buffer */
+	void *data;	/* Buffer data in shared memory */
+};
+
+struct xshmchr_char_dev {
+	struct xshm_dev *xshm;
+	struct kref kref;
+	struct ringbuf rx, tx;
+	u32 conn_state;
+	char name[256];
+	struct miscdevice misc;
+	int file_mode;
+
+	/* Access to this struct and below layers */
+	struct mutex mutex;
+	wait_queue_head_t mgmt_wq;
+	/* List of misc test devices */
+	struct list_head list_field;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs_device_dir;
+	atomic_t num_open;
+	atomic_t num_close;
+	atomic_t num_read;
+	atomic_t num_read_block;
+	atomic_t num_read_bytes;
+
+	atomic_t num_write;
+	atomic_t num_write_block;
+	atomic_t num_write_bytes;
+
+	atomic_t num_init;
+	atomic_t num_init_resp;
+	atomic_t num_deinit;
+	atomic_t num_deinit_resp;
+	atomic_t num_remote_teardown_ind;
+
+#endif
+};
+
+static void xshm_release(struct kref *kref)
+{
+	struct xshmchr_char_dev *dev;
+	dev = container_of(kref, struct xshmchr_char_dev, kref);
+	xdev_vdbg(dev, "Freeing device\n");
+	kfree(dev);
+}
+
+static void xshmchr_get(struct xshmchr_char_dev *dev)
+{
+	kref_get(&dev->kref);
+}
+
+static void xshmchr_put(struct xshmchr_char_dev *dev)
+{
+	kref_put(&dev->kref, xshm_release);
+}
+
+static inline unsigned int ringbuf_empty(struct ringbuf *rb)
+{
+	return *rb->wi == *rb->ri;
+}
+
+static inline unsigned int ringbuf_full(struct ringbuf *rb)
+{
+	return (le32_to_cpu(*rb->wi) + 1) % rb->size == le32_to_cpu(*rb->ri);
+}
+
+static int insert_ringbuf(struct ringbuf *rb, const char __user *from,
+		u32 len)
+{
+	u32 wi = le32_to_cpu(*rb->wi);
+	u32 ri = le32_to_cpu(*rb->ri);
+	u32 cpylen, cpylen2 = 0, notcpy;
+
+	pr_devel("insert: wi:%d ri:%d len:%d\n", wi, ri, len);
+	if (wi >= ri) {
+		len = min(len, rb->size - 1 - wi + ri);
+		cpylen = min(rb->size, wi + len) - wi;
+
+		/* Write is ahead of read, copy 'cpylen' data from 'wi' */
+		notcpy = copy_from_user(rb->data + wi, from, cpylen);
+		if (cpylen > 0 && notcpy == cpylen)
+			return -EIO;
+
+		if (cpylen < len && notcpy == 0) {
+			cpylen2 = min(ri - 1 , len - cpylen);
+
+			/* We have wrapped copy 'cpylen2' from start */
+			notcpy = copy_from_user(rb->data, from + cpylen,
+					cpylen2);
+		}
+	} else {
+		cpylen = min(ri - 1 - wi , len);
+
+		/* Read is ahead of write, copy from wi to (ri - 1) */
+		notcpy = copy_from_user(rb->data + wi, from, cpylen);
+		if (cpylen > 0 && notcpy == cpylen)
+			return -EIO;
+
+	}
+	/* Do write barrier before updating index */
+	smp_wmb();
+	*rb->wi = cpu_to_le32((wi + cpylen + cpylen2 - notcpy) % rb->size);
+	pr_devel("write ringbuf: wi: %d->%d l:%d\n",
+			wi, le32_to_cpu(*rb->wi), cpylen + cpylen2);
+	return cpylen + cpylen2 - notcpy;
+}
+
+static int extract_ringbuf(struct ringbuf *rb, void __user *to, u32 len)
+{
+	u32 wi = le32_to_cpu(*rb->wi);
+	u32 ri = le32_to_cpu(*rb->ri);
+	u32 cpylen = 0, cpylen2 = 0, notcpy;
+
+	pr_devel("extract: wi:%d ri:%d len:%d\n", wi, ri, len);
+	if (ri <= wi) {
+		len = min(wi - ri, len);
+
+		/* Read is ahead of write, copy 'len' data from 'ri' */
+		notcpy = copy_to_user(to, rb->data + ri, len);
+		if (len > 0 && notcpy == len)
+			return -EIO;
+
+		/* Do write barrier before updating index */
+		smp_wmb();
+		*rb->ri = cpu_to_le32(ri + len - notcpy);
+		pr_devel("read ringbuf: ri: %d->%d len:%d\n",
+			ri, le32_to_cpu(*rb->ri), len - notcpy);
+
+		return len - notcpy;
+	} else {
+		/* wr >= ri */
+		cpylen = min(rb->size - ri, len);
+
+		/* Write is ahead, copy 'cpylen' data from ri until end */
+		notcpy = copy_to_user(to, rb->data + ri, cpylen);
+		if (cpylen > 0 && notcpy == cpylen)
+			return -EIO;
+		if (cpylen < len && notcpy == 0) {
+			cpylen2 = min(wi , len - cpylen);
+			/* we have wrapped copy from [0 .. cpylen2] */
+			notcpy = copy_to_user(to + cpylen, rb->data, cpylen2);
+		}
+		/* Do write barrier before updating index */
+		smp_wmb();
+
+		*rb->ri = cpu_to_le32((ri + cpylen + cpylen2 - notcpy)
+						% rb->size);
+		pr_devel("read ringbuf: ri: %d->%d cpylen:%d\n",
+			ri, le32_to_cpu(*rb->ri), cpylen + cpylen2 - notcpy);
+
+		return cpylen + cpylen2 - notcpy;
+	}
+}
+
+static void drain_ringbuf(struct xshmchr_char_dev *dev)
+{
+	/* Empty the ringbuf. */
+	*dev->xshm->cfg.rx.read = *dev->xshm->cfg.rx.write;
+	*dev->xshm->cfg.tx.write = *dev->xshm->cfg.tx.read;
+}
+
+static int open_cb(void *drv)
+{
+	struct xshmchr_char_dev *dev = drv;
+
+	pr_xchrstate(dev, "enter");
+	dbfs_atomic_inc(&dev->num_init_resp);
+	/* Signal reader that data is available. */
+	WARN_ON(!STATE_IS_OPEN(dev));
+	SET_PENDING_OFF(dev);
+	wake_up_interruptible_all(&dev->mgmt_wq);
+	pr_xchrstate(dev, "exit");
+	return 0;
+}
+
+static void close_cb(void *drv)
+{
+	struct xshmchr_char_dev *dev = drv;
+
+	pr_xchrstate(dev, "enter");
+	dbfs_atomic_inc(&dev->num_remote_teardown_ind);
+	if (STATE_IS_PENDING(dev) && !STATE_IS_OPEN(dev)) {
+		/* Normal close sequence */
+		SET_PENDING_OFF(dev);
+		CLEAR_REMOTE_TEARDOWN(dev);
+		SET_EOF(dev);
+		drain_ringbuf(dev);
+		dev->file_mode = 0;
+	} else {
+		/* Remote teardown, close should be called from user-space */
+		SET_REMOTE_TEARDOWN(dev);
+		SET_PENDING_OFF(dev);
+	}
+
+	wake_up_interruptible_all(&dev->mgmt_wq);
+	pr_xchrstate(dev, "exit");
+}
+
+static int ipc_rx_cb(void *drv)
+{
+	struct xshmchr_char_dev *dev = drv;
+
+	xdev_vdbg(dev, "enter\n");
+
+	if (unlikely(*dev->xshm->cfg.rx.state == cpu_to_le32(XSHM_CLOSED)))
+		return -ESHUTDOWN;
+
+	/*
+	 * Performance could perhaps be improved by having a WAIT
+	 * flag, similar to SOCK_ASYNC_WAITDATA, and only do wake up
+	 * when it's actually needed.
+	 */
+	wake_up_interruptible_all(&dev->mgmt_wq);
+	return 0;
+}
+
+static int ipc_tx_release_cb(void *drv)
+{
+	struct xshmchr_char_dev *dev = drv;
+
+	xdev_vdbg(dev, "enter\n");
+	wake_up_interruptible_all(&dev->mgmt_wq);
+	return 0;
+}
+
+/* Device Read function called from Linux kernel */
+static ssize_t xshmchr_chrread(struct file *filp, char __user *buf,
+	 size_t count, loff_t *f_pos)
+{
+	unsigned int len = 0;
+	int result;
+	struct xshmchr_char_dev *dev = filp->private_data;
+	ssize_t ret = -EIO;
+
+	if (dev == NULL) {
+		xdev_dbg(dev, "private_data not set!\n");
+		return -EBADFD;
+	}
+
+	/* I want to be alone on dev (except status and queue) */
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		return -ERESTARTSYS;
+	}
+	xshmchr_get(dev);
+
+	if (!STATE_IS_OPEN(dev)) {
+		/* Device is closed or closing. */
+		if (!STATE_IS_PENDING(dev)) {
+			xdev_dbg(dev, "device is closed (by remote)\n");
+			ret = -ECONNRESET;
+		} else {
+			xdev_dbg(dev, "device is closing...\n");
+			ret = -EBADF;
+		}
+		goto read_error;
+	}
+
+	dbfs_atomic_inc(&dev->num_read);
+
+	/* Device is open or opening. */
+	if (STATE_IS_PENDING(dev)) {
+		xdev_vdbg(dev, "device is opening...\n");
+
+		dbfs_atomic_inc(&dev->num_read_block);
+		if (filp->f_flags & O_NONBLOCK) {
+			/* We can't block. */
+			xdev_dbg(dev, "exit: state pending and O_NONBLOCK\n");
+			ret = -EAGAIN;
+			goto read_error;
+		}
+
+		/*
+		 * To reach here client must do blocking open,
+		 * and start read() before open completes. This is
+		 * quite quirky, but let's handle it anyway.
+		 */
+		result =
+		    wait_event_interruptible(dev->mgmt_wq,
+					!STATE_IS_PENDING(dev) ||
+				    STATE_IS_REMOTE_TEARDOWN(dev));
+
+		if (result == -ERESTARTSYS) {
+			xdev_dbg(dev, "wait_event_interruptible"
+				 " woken by a signal (1)\n");
+			ret = -ERESTARTSYS;
+			goto read_error;
+		}
+		if (STATE_IS_REMOTE_TEARDOWN(dev)) {
+			xdev_dbg(dev,
+				"received remote_shutdown indication (1)\n");
+			ret = -ESHUTDOWN;
+			goto read_error;
+		}
+	}
+
+	/* Block if we don't have any received buffers.
+	 * The queue has its own lock.
+	 */
+	while (ringbuf_empty(&dev->rx)) {
+
+		if (filp->f_flags & O_NONBLOCK) {
+			xdev_vdbg(dev, "exit: O_NONBLOCK\n");
+			ret = -EAGAIN;
+			goto read_error;
+		}
+
+		/* Let writers in. */
+		mutex_unlock(&dev->mutex);
+
+		xdev_vdbg(dev, "wait for data\n");
+		/* Block reader until data arrives or device is closed. */
+		if (wait_event_interruptible(dev->mgmt_wq,
+				!ringbuf_empty(&dev->rx)
+				|| STATE_IS_REMOTE_TEARDOWN(dev)
+				|| !STATE_IS_OPEN(dev)) == -ERESTARTSYS) {
+			xdev_vdbg(dev, "event_interruptible woken by "
+				 "a signal, signal_pending(current) = %d\n",
+				signal_pending(current));
+			return -ERESTARTSYS;
+		}
+
+		xdev_vdbg(dev, "wakeup readq\n");
+
+		if (STATE_IS_REMOTE_TEARDOWN(dev) && ringbuf_empty(&dev->rx)) {
+			if (!STATE_IS_EOF(dev)) {
+				xdev_dbg(dev, "First EOF OK\n");
+				SET_EOF(dev);
+				ret = 0;
+				goto error_nolock;
+			}
+			xdev_dbg(dev, "2'nd EOF - remote_shutdown\n");
+			ret = -ECONNRESET;
+			goto error_nolock;
+		}
+
+		/* I want to be alone on dev (except status and queue). */
+		if (mutex_lock_interruptible(&dev->mutex)) {
+			xdev_dbg(dev, "mutex_lock_interruptible"
+					" got signalled\n");
+			return -ERESTARTSYS;
+		}
+
+		if (!STATE_IS_OPEN(dev)) {
+			/* Someone closed the link, report error. */
+			xdev_dbg(dev, "remote end shutdown!\n");
+			ret = -EBADF;
+			goto read_error;
+		}
+	}
+
+	xdev_vdbg(dev, "copy data\n");
+	len = extract_ringbuf(&dev->rx, buf, count);
+	if (len <= 0) {
+		xdev_dbg(dev, "Extracting from ringbuf failed\n");
+		ret = -EINVAL;
+		goto read_error;
+	}
+
+	/* Signal to modem that data is read from ringbuf */
+
+	dev->xshm->ipc_rx_release(dev->xshm, false);
+
+	dbfs_atomic_add(len, &dev->num_read_bytes);
+	/* Let the others in. */
+	mutex_unlock(&dev->mutex);
+	xshmchr_put(dev);
+	return len;
+
+read_error:
+	mutex_unlock(&dev->mutex);
+error_nolock:
+	xshmchr_put(dev);
+	return ret;
+}
+
+/* Device write function called from Linux kernel (misc device) */
+static ssize_t xshmchr_chrwrite(struct file *filp, const char __user *buf,
+		      size_t count, loff_t *f_pos)
+{
+	struct xshmchr_char_dev *dev = filp->private_data;
+	ssize_t ret = -EIO;
+	int result;
+	uint len = 0;
+
+	if (dev == NULL) {
+		xdev_dbg(dev, "private_data not set!\n");
+		ret = -EBADFD;
+		goto write_error_no_unlock;
+	}
+
+	pr_xchrstate(dev, "enter");
+
+	/* I want to be alone on dev (except status and queue). */
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		ret = -ERESTARTSYS;
+		goto write_error_no_unlock;
+	}
+	xshmchr_get(dev);
+
+	dbfs_atomic_inc(&dev->num_write);
+	if (!STATE_IS_OPEN(dev)) {
+		/* Device is closed or closing. */
+		if (!STATE_IS_PENDING(dev)) {
+			xdev_dbg(dev, "device is closed (by remote)\n");
+			ret = -EPIPE;
+		} else {
+			xdev_dbg(dev, "device is closing...\n");
+			ret = -EBADF;
+		}
+		goto write_error;
+	}
+
+	/* Device is open or opening. */
+	if (STATE_IS_PENDING(dev)) {
+		xdev_dbg(dev, "device is opening...\n");
+
+		dbfs_atomic_inc(&dev->num_write_block);
+		if (filp->f_flags & O_NONBLOCK) {
+			/* We can't block */
+			xdev_dbg(dev, "exit: state pending and O_NONBLOCK\n");
+			ret = -EAGAIN;
+			goto write_error;
+		}
+
+		/* Blocking mode; state is pending and we need to wait
+		 * for its conclusion. (Shutdown_ind set pending off.)
+		 */
+		result =
+		    wait_event_interruptible(dev->mgmt_wq,
+					!STATE_IS_PENDING(dev) ||
+					STATE_IS_REMOTE_TEARDOWN(dev));
+		if (result == -ERESTARTSYS) {
+			xdev_dbg(dev, "wait_event_interruptible"
+				 " woken by a signal (1)\n");
+			ret = -ERESTARTSYS;
+			goto write_error;
+		}
+	}
+	if (STATE_IS_REMOTE_TEARDOWN(dev)) {
+		xdev_dbg(dev, "received remote_shutdown indication\n");
+		ret = -EPIPE;
+		goto write_error;
+	}
+
+	while (ringbuf_full(&dev->tx)) {
+		/* Flow is off. Check non-block flag. */
+		if (filp->f_flags & O_NONBLOCK) {
+			xdev_dbg(dev, "exit: O_NONBLOCK and tx flow off");
+			ret = -EAGAIN;
+			goto write_error;
+		}
+
+		/* Let readers in. */
+		mutex_unlock(&dev->mutex);
+
+		xdev_vdbg(dev, "wait for write space\n");
+		/* Wait until flow is on or device is closed. */
+		if (wait_event_interruptible(dev->mgmt_wq,
+					!ringbuf_full(&dev->tx)
+					|| !STATE_IS_OPEN(dev)
+					|| STATE_IS_REMOTE_TEARDOWN(dev)
+					) == -ERESTARTSYS) {
+			xdev_dbg(dev, "wait_event_interruptible"
+				 " woken by a signal (1)\n");
+			ret = -ERESTARTSYS;
+			goto write_error_no_unlock;
+		}
+
+		/* I want to be alone on dev (except status and queue). */
+		if (mutex_lock_interruptible(&dev->mutex)) {
+			xdev_dbg(dev, "mutex_lock_interruptible "
+					"got signalled\n");
+			ret = -ERESTARTSYS;
+			goto write_error_no_unlock;
+		}
+
+		xdev_vdbg(dev, "wakeup got write space\n");
+		if (!STATE_IS_OPEN(dev)) {
+			/* Someone closed the link, report error. */
+			xdev_dbg(dev, "remote end shutdown!\n");
+			ret = -EPIPE;
+			goto write_error;
+		}
+		if (STATE_IS_REMOTE_TEARDOWN(dev)) {
+			xdev_dbg(dev, "received remote_shutdown indication\n");
+			ret = -ESHUTDOWN;
+			goto write_error;
+		}
+	}
+	len = insert_ringbuf(&dev->tx, buf, count);
+	xdev_vdbg(dev, "inserted %d bytes\n", len);
+	if (len <= 0) {
+		xdev_dbg(dev, "transmit failed, error = %d\n",
+				(int) ret);
+		goto write_error;
+	}
+
+	dbfs_atomic_add(len, &dev->num_write_bytes);
+
+	/* Signal to modem that data is put in ringbuf */
+	dev->xshm->ipc_tx(dev->xshm);
+
+	mutex_unlock(&dev->mutex);
+	xshmchr_put(dev);
+	return len;
+
+write_error:
+	mutex_unlock(&dev->mutex);
+write_error_no_unlock:
+	xshmchr_put(dev);
+	return ret;
+}
+
+static unsigned int xshmchr_chrpoll(struct file *filp, poll_table *waittab)
+{
+	struct xshmchr_char_dev *dev = filp->private_data;
+	unsigned int mask = 0;
+
+	if (dev == NULL) {
+		xdev_dbg(dev, "private_data not set!\n");
+		return -EBADFD;
+	}
+
+	/* I want to be alone on dev (except status and queue). */
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		mask |= POLLERR;
+		goto out_unlocked;
+	}
+	xshmchr_get(dev);
+
+	if (STATE_IS_REMOTE_TEARDOWN(dev)) {
+		xdev_dbg(dev, "not open\n");
+		mask |= POLLRDHUP | POLLHUP;
+		goto out;
+	}
+
+	xdev_vdbg(dev, "poll wait\n");
+	poll_wait(filp, &dev->mgmt_wq, waittab);
+
+	if (STATE_IS_OPEN(dev) && STATE_IS_PENDING(dev))
+		goto out;
+
+	if (!ringbuf_empty(&dev->rx))
+		mask |= (POLLIN | POLLRDNORM);
+
+	if (!ringbuf_full(&dev->tx))
+		mask |= (POLLOUT | POLLWRNORM);
+
+out:
+	mutex_unlock(&dev->mutex);
+out_unlocked:
+	xdev_vdbg(dev, "poll return mask=0x%04x\n", mask);
+	xshmchr_put(dev);
+	return mask;
+}
+
+/* Usage:
+ * minor >= 0 : find from minor
+ * minor < 0 and name == name : find from name
+ * minor < 0 and name == NULL : get first
+ */
+
+static struct xshmchr_char_dev *find_device(int minor, char *name,
+					 int remove_from_list)
+{
+	struct list_head *list_node;
+	struct list_head *n;
+	struct xshmchr_char_dev *dev = NULL;
+	struct xshmchr_char_dev *tmp;
+	spin_lock(&list_lock);
+	pr_devel("start looping\n");
+	list_for_each_safe(list_node, n, &xshmchr_chrdev_list) {
+		tmp = list_entry(list_node, struct xshmchr_char_dev,
+				list_field);
+		if (minor >= 0) {	/* find from minor */
+			if (tmp->misc.minor == minor)
+				dev = tmp;
+
+		} else if (name) {	/* find from name */
+			if (!strncmp(tmp->name, name, sizeof(tmp->name)))
+				dev = tmp;
+		} else {	/* take first */
+			dev = tmp;
+		}
+
+		if (dev) {
+			xdev_vdbg(dev, "match %d, %s\n",
+				      minor, name);
+			if (remove_from_list)
+				list_del(list_node);
+			break;
+		}
+	}
+	spin_unlock(&list_lock);
+	return dev;
+}
+
+static int xshmchr_chropen(struct inode *inode, struct file *filp)
+{
+	struct xshmchr_char_dev *dev = NULL;
+	int result = -1;
+	int minor = iminor(inode);
+	int mode = 0;
+	int ret = -EIO;
+
+	dev = find_device(minor, NULL, 0);
+	pr_xchrstate(dev, "enter");
+
+	if (dev == NULL) {
+		xdev_dbg(dev, "Could not find device\n");
+		return -EBADF;
+	}
+
+	/* I want to be alone on dev (except status and queue). */
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		return -ERESTARTSYS;
+	}
+
+	xshmchr_get(dev);
+	dbfs_atomic_inc(&dev->num_open);
+	filp->private_data = dev;
+
+	switch (filp->f_flags & O_ACCMODE) {
+	case O_RDONLY:
+		mode = CHR_READ_FLAG;
+		break;
+	case O_WRONLY:
+		mode = CHR_WRITE_FLAG;
+		break;
+	case O_RDWR:
+		mode = CHR_READ_FLAG | CHR_WRITE_FLAG;
+		break;
+	}
+
+	/* If device is not open, make sure device is in fully closed state. */
+	if (!STATE_IS_OPEN(dev)) {
+		/* Has link close response been received
+		 * (if we ever sent it)?
+		 */
+		if (STATE_IS_PENDING(dev)) {
+			/* Still waiting for close response from remote.
+			 * If opened non-blocking, report "would block".
+			 */
+			if (filp->f_flags & O_NONBLOCK) {
+				xdev_vdbg(dev,
+					"exit: O_NONBLOCK && close pending\n");
+				ret = -EAGAIN;
+				goto open_error;
+			}
+
+			xdev_vdbg(dev, "WAIT for close response from remote\n");
+
+			/*
+			 * Blocking mode; close is pending and we need to wait
+			 * for its conclusion. However modem may be dead,
+			 * or resureccted and alive waiting for
+			 * an open ack.
+			 * It's hard to get this rigth - if state is
+			 * pending. We have missed a state update,
+			 * let's just wait for ack, and then proceede
+			 * with watever state we have.
+			 */
+			result =
+			    wait_event_interruptible_timeout(dev->mgmt_wq,
+					    !STATE_IS_PENDING(dev) ||
+					    STATE_IS_REMOTE_TEARDOWN(dev),
+					    OPEN_TOUT);
+
+			if (result == -ERESTARTSYS) {
+				xdev_dbg(dev, "wait_event_interruptible"
+					" woken by a signal (1)\n");
+				ret = -ERESTARTSYS;
+				goto open_error;
+			}
+
+			if (result == 0) {
+				SET_PENDING_OFF(dev);
+				pr_xchrstate(dev,
+				    "Timeout -pending close -Clear pending");
+			} else
+				pr_xchrstate(dev, "wakeup (wait for close)");
+		}
+	}
+
+	/* Device is now either closed, pending open or open */
+	if (STATE_IS_OPEN(dev) && !STATE_IS_PENDING(dev)) {
+		/* Open */
+		xdev_vdbg(dev, "Device is already opened (dev=%p) check"
+				"access f_flags = 0x%x file_mode = 0x%x\n",
+				dev, mode, dev->file_mode);
+
+		if (mode & dev->file_mode) {
+			xdev_vdbg(dev, "Access mode already in use 0x%x\n",
+					mode);
+			ret = -EBUSY;
+			goto open_error;
+		}
+	} else {
+
+		/* We are closed or pending open.
+		 * If closed:	    send link setup
+		 * If pending open: link setup already sent (we could have been
+		 *		    interrupted by a signal last time)
+		 */
+		if (!STATE_IS_OPEN(dev)) {
+			/* First opening of file; do connect */
+
+			SET_STATE_OPEN(dev);
+			SET_PENDING_ON(dev);
+			CLEAR_EOF(dev);
+			/* Send "open" by resetting indexes */
+			result = dev->xshm->open(dev->xshm);
+
+			if (result < 0) {
+				xdev_dbg(dev, "can't open channel\n");
+				ret = -EIO;
+				SET_STATE_CLOSED(dev);
+				SET_PENDING_OFF(dev);
+				goto open_error;
+			}
+			dbfs_atomic_inc(&dev->num_init);
+		}
+
+		/* If opened non-blocking, report "success".
+		 */
+		if (filp->f_flags & O_NONBLOCK) {
+			xdev_vdbg(dev, "EXIT: O_NONBLOCK success\n");
+			ret = 0;
+			goto open_success;
+		}
+
+		xdev_vdbg(dev, "WAIT for connect response\n");
+		/*
+		 * misc_open holds a global mutex anyway so there is no
+		 * reason to release our own while waiting
+		 */
+		result =
+		    wait_event_interruptible_timeout(dev->mgmt_wq,
+				    !STATE_IS_PENDING(dev) ||
+				    STATE_IS_REMOTE_TEARDOWN(dev),
+				    OPEN_TOUT);
+		if (result == 0) {
+			xdev_dbg(dev, "wait_event_interruptible timeout (1)\n");
+			ret = -ETIMEDOUT;
+			goto open_error;
+		}
+		if (result == -ERESTARTSYS) {
+			xdev_dbg(dev, "wait_event_interruptible woken by sig");
+			ret = -ERESTARTSYS;
+			goto open_error;
+		}
+		if (STATE_IS_REMOTE_TEARDOWN(dev)) {
+			xdev_dbg(dev, "received remote_shutdown indication\n");
+			ret = -ESHUTDOWN;
+			goto open_error;
+		}
+
+		pr_xchrstate(dev, "wakeup (wait for open)");
+		if (!STATE_IS_OPEN(dev)) {
+			/* Lower layers said "no". */
+			xdev_dbg(dev, "xshmchr_chropen: Closed received\n");
+			ret = -EPIPE;
+			goto open_error;
+		}
+
+		xdev_vdbg(dev, "connect received\n");
+	}
+open_success:
+	/* Open is OK. */
+	dev->file_mode |= mode;
+
+	xdev_vdbg(dev, "file mode = %x\n", dev->file_mode);
+	pr_xchrstate(dev, "exit");
+
+	mutex_unlock(&dev->mutex);
+	xshmchr_put(dev);
+	return 0;
+
+open_error:
+	dev->xshm->close(dev->xshm);
+	SET_STATE_CLOSED(dev);
+	SET_PENDING_OFF(dev);
+	mutex_unlock(&dev->mutex);
+	xshmchr_put(dev);
+	return ret;
+}
+
+static int xshmchr_chrrelease(struct inode *inode, struct file *filp)
+{
+	struct xshmchr_char_dev *dev = NULL;
+	int minor = iminor(inode);
+	int mode = 0;
+
+
+	dev = find_device(minor, NULL, 0);
+	if (dev == NULL) {
+		xdev_dbg(dev, "Could not find device\n");
+		return -EBADF;
+	}
+
+	pr_xchrstate(dev, "enter");
+
+	/* I want to be alone on dev (except status queue). */
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		return -ERESTARTSYS;
+	}
+
+	xshmchr_get(dev);
+	dbfs_atomic_inc(&dev->num_close);
+
+	/* Is the device open? */
+	if (!STATE_IS_OPEN(dev)) {
+		xdev_vdbg(dev, "Device not open (dev=%p)\n",
+			      dev);
+		mutex_unlock(&dev->mutex);
+		xshmchr_put(dev);
+		return 0;
+	}
+
+	switch (filp->f_flags & O_ACCMODE) {
+	case O_RDONLY:
+		mode = CHR_READ_FLAG;
+		break;
+	case O_WRONLY:
+		mode = CHR_WRITE_FLAG;
+		break;
+	case O_RDWR:
+		mode = CHR_READ_FLAG | CHR_WRITE_FLAG;
+		break;
+	}
+
+	dev->file_mode &= ~mode;
+	if (dev->file_mode) {
+		xdev_vdbg(dev, "Device is kept open by someone else, "
+			 " don't close. XSHMCHR connection - file_mode = %x\n",
+			 dev->file_mode);
+		mutex_unlock(&dev->mutex);
+		xshmchr_put(dev);
+		return 0;
+	}
+
+	/* IS_CLOSED have double meaning:
+	 * 1) Spontanous Remote Shutdown Request.
+	 * 2) Ack on a channel teardown(disconnect)
+	 * Must clear bit, in case we previously received
+	 * a remote shudown request.
+	 */
+
+	SET_STATE_CLOSED(dev);
+	SET_PENDING_ON(dev);
+	CLEAR_REMOTE_TEARDOWN(dev);
+	SET_EOF(dev);
+
+	dev->xshm->close(dev->xshm);
+
+	dbfs_atomic_inc(&dev->num_deinit);
+
+	/* Empty the ringbuf */
+	drain_ringbuf(dev);
+	dev->file_mode = 0;
+
+	mutex_unlock(&dev->mutex);
+	pr_xchrstate(dev, "exit");
+	xshmchr_put(dev);
+	return 0;
+}
+
+static const struct file_operations xshmchr_chrfops = {
+	.owner = THIS_MODULE,
+	.read = xshmchr_chrread,
+	.write = xshmchr_chrwrite,
+	.open = xshmchr_chropen,
+	.release = xshmchr_chrrelease,
+	.poll = xshmchr_chrpoll,
+};
+
+static int cfshm_probe(struct xshm_dev *xshm)
+
+{
+	struct xshmchr_char_dev *dev = NULL;
+	int result;
+
+	pr_devel("cfshm_probe called\n");
+	if (xshm == NULL)
+		return 0;
+
+	/* Allocate device */
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+
+	if (!dev) {
+		pr_err("kmalloc failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+	kref_init(&dev->kref);
+
+	dev->xshm = xshm;
+	mutex_init(&dev->mutex);
+	init_waitqueue_head(&dev->mgmt_wq);
+
+	/* Fill in some information concerning the misc device. */
+	dev->misc.minor = MISC_DYNAMIC_MINOR;
+	if (strlen(xshm->cfg.name) == 0) {
+		xdev_dbg(dev, "XSHM device does not have a name\n");
+		return -EINVAL;
+	}
+	sprintf(dev->name, "%s", xshm->cfg.name);
+	dev->misc.name = dev->name;
+	dev->misc.fops = &xshmchr_chrfops;
+
+	dev->tx.ri = xshm->cfg.tx.read;
+	dev->tx.wi = xshm->cfg.tx.write;
+	dev->tx.data = xshm->cfg.tx.addr;
+	dev->tx.size = xshm->cfg.tx.ch_size - 1;
+
+	dev->rx.ri = xshm->cfg.rx.read;
+	dev->rx.wi = xshm->cfg.rx.write;
+	dev->rx.data = xshm->cfg.rx.addr;
+	dev->rx.size = xshm->cfg.rx.ch_size - 1;
+	if (dev->rx.size < 2 || dev->tx.size < 2) {
+		dev->rx.size = 0;
+		dev->tx.size = 0;
+		xdev_dbg(dev, "dev:error - channel size too small\n");
+		return -EINVAL;
+	}
+	dev->xshm->ipc_rx_cb = ipc_rx_cb;
+	dev->xshm->ipc_tx_release_cb = ipc_tx_release_cb;
+	dev->xshm->open_cb = open_cb;
+	dev->xshm->close_cb = close_cb;
+	dev->xshm->driver_data = dev;
+
+	mutex_lock(&dev->mutex);
+
+	/* Register the device. */
+	dev->misc.parent = &xshm->dev;
+	pr_devel("register dev:%s chr=%s(%s) dev=%p\n",
+			dev_name(&dev->xshm->dev),
+			dev->name, xshm->cfg.name, dev);
+	result = misc_register(&dev->misc);
+
+	/* Lock in order to try to stop someone from opening the device
+	 * too early. The misc device has its own lock. We cannot take our
+	 * lock until misc_register() is finished, because in open() the
+	 * locks are taken in this order (misc first and then dev).
+	 * So anyone managing to open the device between the misc_register
+	 * and the mutex_lock will get a "device not found" error. Don't
+	 * think it can be avoided.
+	 */
+
+	if (result < 0) {
+		pr_warn("error - %d, can't register misc\n",
+				result);
+		mutex_unlock(&dev->mutex);
+		goto err_failed;
+	}
+
+	xdev_vdbg(dev, "Registered dev with name=%s minor=%d, dev=%p\n",
+			dev->misc.name, dev->misc.minor, dev->misc.this_device);
+
+	SET_STATE_CLOSED(dev);
+	SET_PENDING_OFF(dev);
+	CLEAR_REMOTE_TEARDOWN(dev);
+	CLEAR_EOF(dev);
+
+	/* Add the device. */
+	spin_lock(&list_lock);
+	list_add(&dev->list_field, &xshmchr_chrdev_list);
+	spin_unlock(&list_lock);
+
+#ifdef CONFIG_DEBUG_FS
+	if (debugfsdir != NULL) {
+		dev->debugfs_device_dir =
+		    debugfs_create_dir(dev->misc.name, debugfsdir);
+		debugfs_create_u32("conn_state", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir, &dev->conn_state);
+		debugfs_create_u32("num_open", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_open);
+		debugfs_create_u32("num_close", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_close);
+		debugfs_create_u32("num_init", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_init);
+		debugfs_create_u32("num_init_resp", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_init_resp);
+		debugfs_create_u32("num_deinit", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_deinit);
+		debugfs_create_u32("num_deinit_resp", S_IRUSR | S_IWUSR,
+				   dev->debugfs_device_dir,
+				   (u32 *) &dev->num_deinit_resp);
+		debugfs_create_u32("num_remote_teardown_ind",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_remote_teardown_ind);
+		debugfs_create_u32("num_read",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_read);
+		debugfs_create_u32("num_read_block",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_read_block);
+		debugfs_create_u32("num_read_bytes",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_read_bytes);
+		debugfs_create_u32("num_write",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_write);
+		debugfs_create_u32("num_write_block",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_write_block);
+		debugfs_create_u32("num_write_bytes",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				   (u32 *) &dev->num_write_bytes);
+
+		debugfs_create_u32("rx_write_index",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.rx.write);
+		debugfs_create_u32("rx_read_index",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.rx.read);
+		debugfs_create_u32("rx_state",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.rx.state);
+		debugfs_create_u32("tx_write_index",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.tx.write);
+		debugfs_create_u32("tx_read_index",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.tx.read);
+		debugfs_create_u32("tx_state",
+				   S_IRUSR | S_IWUSR, dev->debugfs_device_dir,
+				(u32 *) dev->xshm->cfg.tx.state);
+
+	}
+#endif
+	mutex_unlock(&dev->mutex);
+	return 0;
+err_failed:
+	xshmchr_put(dev);
+	return result;
+}
+
+static int chrdev_remove(struct xshmchr_char_dev *dev)
+{
+	if (!dev)
+		return -EBADF;
+
+	if (STATE_IS_OPEN(dev)) {
+		xdev_dbg(dev, "Device is opened "
+			 "(dev=%p) file_mode = 0x%x\n",
+			 dev, dev->file_mode);
+		SET_STATE_CLOSED(dev);
+		SET_PENDING_OFF(dev);
+		wake_up_interruptible_all(&dev->mgmt_wq);
+	}
+
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		xdev_dbg(dev, "mutex_lock_interruptible got signalled\n");
+		xshmchr_put(dev);
+		return -ERESTARTSYS;
+	}
+
+	drain_ringbuf(dev);
+
+	misc_deregister(&dev->misc);
+
+	/* Remove from list. */
+	list_del(&dev->list_field);
+
+#ifdef CONFIG_DEBUG_FS
+	if (dev->debugfs_device_dir != NULL)
+		debugfs_remove_recursive(dev->debugfs_device_dir);
+#endif
+
+	mutex_unlock(&dev->mutex);
+	xshmchr_put(dev);
+	return 0;
+}
+
+static void cfshm_remove(struct xshm_dev *xshm)
+{
+	int err;
+
+	pr_devel("unregister pdev:%s chr=%s xshm=%p\n",
+			dev_name(&xshm->dev),
+			xshm->cfg.name, xshm);
+
+	err = chrdev_remove(xshm->driver_data);
+	if (err)
+		pr_debug("removing char-dev:%s failed.%d\n",
+					xshm->cfg.name, err);
+
+	xshm->ipc_rx_cb = NULL;
+	xshm->ipc_tx_release_cb = NULL;
+	xshm->open_cb = NULL;
+	xshm->close_cb = NULL;
+	xshm->driver_data = NULL;
+}
+
+static struct xshm_driver cfshm_drv = {
+	.mode = XSHM_STREAM_MODE,
+	.probe = cfshm_probe,
+	.remove = cfshm_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+
+static int __init xshmchr_chrinit_module(void)
+{
+	int err;
+	pr_devel("xshm init\n");
+	spin_lock_init(&list_lock);
+
+	/* Register xshm driver. */
+	err = xshm_register_driver(&cfshm_drv);
+	if (err) {
+		printk(KERN_ERR "Could not register SHM driver: %d.\n",
+			err);
+		goto err_dev_register;
+	}
+
+#ifdef CONFIG_DEBUG_FS
+	debugfsdir = debugfs_create_dir("xshm_chr", NULL);
+#endif
+
+ err_dev_register:
+	return err;
+
+}
+
+static void __exit xshmchr_chrexit_module(void)
+{
+	int result;
+	struct xshmchr_char_dev *dev = NULL;
+
+	/* Unregister xshm driver. */
+	xshm_unregister_driver(&cfshm_drv);
+
+	do {
+		/* Remove any device (the first in the list). */
+		dev = find_device(-1, NULL, 0);
+		result = chrdev_remove(dev);
+	} while (result == 0);
+
+#ifdef CONFIG_DEBUG_FS
+	if (debugfsdir != NULL)
+		debugfs_remove_recursive(debugfsdir);
+#endif
+
+}
+
+module_init(xshmchr_chrinit_module);
+module_exit(xshmchr_chrexit_module);
diff --git a/drivers/xshm/xshm_dev.c b/drivers/xshm/xshm_dev.c
new file mode 100644
index 0000000..bfd771c
--- /dev/null
+++ b/drivers/xshm/xshm_dev.c
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s:" fmt, __func__
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/firmware.h>
+#include <linux/c2c_genio.h>
+#include <linux/xshm/xshm_dev.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sjur Brændland <sjur.brandeland@stericsson.com>");
+
+static int xshm_inactivity_timeout = 1000;
+module_param(xshm_inactivity_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(xshm_inactivity_timeout, "Inactivity timeout, ms.");
+
+struct xshm_parent {
+	struct device dev;
+	bool ready_for_ipc;
+	bool ready_for_caif;
+	spinlock_t timer_lock;
+	int inactivity_timeout;
+	struct timer_list inactivity_timer;
+	bool power_on;
+};
+
+struct xshm_parent *parent_dev;
+
+#define xdev_dbg(dev, fmt, arg...) dev_dbg(&dev->dev, pr_fmt(fmt), ##arg)
+#define xdev_vdbg(dev, fmt, arg...) dev_vdbg(&dev->dev, pr_fmt(fmt), ##arg)
+#define pr_xshmstate(dev, str, arg...)					\
+	xdev_vdbg(dev, str "STATE: %s txch:%s(%p) rxch:%s(%p)\n", ##arg,\
+			dev->state == XSHM_DEV_OPEN ? "open" : "close", \
+			*dev->cfg.tx.state == cpu_to_le32(XSHM_OPEN) ?	\
+			"open" : "close",				\
+			dev->cfg.tx.state,				\
+			*dev->cfg.rx.state == cpu_to_le32(XSHM_OPEN) ?	\
+			"open" : "close",				\
+			dev->cfg.rx.state)
+
+static void inactivity_tout(unsigned long arg)
+{
+	unsigned long flags;
+	pr_devel("enter\n");
+	spin_lock_irqsave(&parent_dev->timer_lock, flags);
+	/*
+	 * This is paranoia, but if timer is reactivated
+	 * before this tout function is scheduled,
+	 * we just ignore this timeout.
+	 */
+	if (timer_pending(&parent_dev->inactivity_timer))
+		goto out;
+
+	if (parent_dev->power_on) {
+		pr_devel("genio power req(off)\n");
+		genio_power_req(false);
+		parent_dev->power_on = false;
+	}
+out:
+	spin_unlock_irqrestore(&parent_dev->timer_lock, flags);
+}
+
+static void activity(void)
+{
+	unsigned long flags;
+	pr_devel("enter\n");
+	spin_lock_irqsave(&parent_dev->timer_lock, flags);
+	if (!parent_dev->power_on) {
+		pr_devel("genio power req(on)\n");
+		genio_power_req(true);
+		parent_dev->power_on = true;
+	}
+	mod_timer(&parent_dev->inactivity_timer,
+			jiffies + parent_dev->inactivity_timeout);
+	spin_unlock_irqrestore(&parent_dev->timer_lock, flags);
+}
+
+static void reset_activity_tout(void)
+{
+	unsigned long flags;
+	pr_devel("enter\n");
+	spin_lock_irqsave(&parent_dev->timer_lock, flags);
+	if (parent_dev->power_on) {
+		genio_power_req(false);
+		parent_dev->power_on = false;
+	}
+	del_timer_sync(&parent_dev->inactivity_timer);
+	spin_unlock_irqrestore(&parent_dev->timer_lock, flags);
+}
+
+static int xshmdev_ipc_tx(struct xshm_dev *dev)
+{
+	xdev_vdbg(dev, "call genio_set_bit(%d)\n", dev->cfg.tx.xfer_bit);
+	activity();
+	return genio_set_bit(dev->cfg.tx.xfer_bit);
+}
+
+static int xshmdev_ipc_rx_release(struct xshm_dev *dev, bool more)
+{
+	xdev_vdbg(dev, "call genio_set_bit(%d)\n", dev->cfg.tx.xfer_bit);
+	activity();
+	return genio_set_bit(dev->cfg.rx.xfer_done_bit);
+}
+
+static int do_open(struct xshm_dev *dev)
+{
+	int err;
+
+	pr_xshmstate(dev, "enter");
+	err = dev->open_cb(dev->driver_data);
+	if (err < 0) {
+		xdev_dbg(dev, "Error - open_cb failed\n");
+
+		/* Make sure ring-buffer is empty i RX and TX direction */
+		*dev->cfg.rx.read = *dev->cfg.rx.write;
+		*dev->cfg.tx.write = *dev->cfg.tx.read;
+		*dev->cfg.tx.state = cpu_to_le32(XSHM_CLOSED);
+		xdev_vdbg(dev, "set state = XSHM_DEV_CLOSED\n");
+		dev->state = XSHM_DEV_CLOSED;
+		return err;
+	}
+
+	/* Check is we already have any data in the pipe */
+	if (*dev->cfg.rx.write != *dev->cfg.rx.read) {
+		xdev_vdbg(dev, "Received data during opening\n");
+		dev->ipc_rx_cb(dev->driver_data);
+	}
+
+	return err;
+}
+
+static void genio_rx_cb(void *data)
+{
+	struct xshm_dev *dev = data;
+
+	pr_xshmstate(dev, "Enter");
+
+	if (likely(dev->state == XSHM_DEV_OPEN)) {
+		if (unlikely(!parent_dev->ready_for_ipc)) {
+			xdev_vdbg(dev, "ready_for_ipc is not yet set\n");
+			return;
+		}
+
+		if (dev->ipc_rx_cb) {
+			int err = dev->ipc_rx_cb(dev->driver_data);
+			if (unlikely(err < 0))
+				goto remote_close;
+		}
+
+	} else if (*dev->cfg.rx.state == cpu_to_le32(XSHM_OPEN)) {
+		pr_xshmstate(dev, "");
+		dev->state = XSHM_DEV_OPEN;
+		if (!parent_dev->ready_for_ipc) {
+			xdev_vdbg(dev, "ready_for_ipc is not yet set\n");
+			return;
+		}
+		if (do_open(dev) < 0)
+			goto open_fail;
+	}
+	return;
+open_fail:
+	pr_xshmstate(dev, "exit open failed");
+	/* Make sure ring-buffer is empty i RX and TX direction */
+	*dev->cfg.rx.read = *dev->cfg.rx.write;
+	*dev->cfg.tx.write = *dev->cfg.tx.read;
+remote_close:
+	*dev->cfg.tx.state = cpu_to_le32(XSHM_CLOSED);
+	dev->state = XSHM_DEV_CLOSED;
+	dev->close_cb(dev->driver_data);
+}
+
+static void genio_tx_release_cb(void *data)
+{
+	struct xshm_dev *dev = data;
+
+	pr_xshmstate(dev, "Enter");
+	if (!parent_dev->ready_for_ipc) {
+		xdev_vdbg(dev, "not ready_for_ipc\n");
+		return;
+	}
+	if (dev->ipc_tx_release_cb)
+		dev->ipc_tx_release_cb(dev->driver_data);
+}
+
+struct xshm_xgroup {
+	bool prohibit;
+	u32 group;
+};
+
+static void check_exclgroup(struct xshm_dev *dev, void *data)
+{
+	struct xshm_xgroup *x = data;
+	if (dev->state == XSHM_DEV_OPEN &&
+		dev->cfg.excl_group != x->group) {
+		x->prohibit = true;
+		xdev_dbg(dev, "Exclusive group "
+				"prohibits device open\n");
+	}
+}
+
+static int xshmdev_open(struct xshm_dev *dev)
+{
+	int err = -EINVAL;
+	struct xshm_xgroup x = {
+		.prohibit = false,
+		.group = dev->cfg.excl_group
+	};
+
+
+	pr_xshmstate(dev, "Enter");
+	if (WARN_ON(dev->ipc_rx_cb == NULL) ||
+			WARN_ON(dev->ipc_tx_release_cb == NULL) ||
+			WARN_ON(dev->open_cb == NULL) ||
+			WARN_ON(dev->close_cb == NULL))
+		goto err;
+
+	xshm_foreach_dev(check_exclgroup, &x);
+	if (x.prohibit) {
+		xdev_dbg(dev, "Exclusive group prohibits device open\n");
+		err = -EPERM;
+		goto err;
+	}
+
+	xdev_vdbg(dev, "call genio_subscribe(%d)\n", dev->cfg.rx.xfer_bit);
+	err = genio_subscribe(dev->cfg.rx.xfer_bit, genio_rx_cb, dev);
+	if (err)
+		goto err;
+
+	xdev_vdbg(dev, "call genio_subscribe(%d)\n", dev->cfg.tx.xfer_done_bit);
+	err = genio_subscribe(dev->cfg.tx.xfer_done_bit,
+			genio_tx_release_cb, dev);
+	if (err)
+		goto err;
+
+	/* Indicate that our side is open and ready for action */
+	*dev->cfg.rx.read = *dev->cfg.rx.write;
+	*dev->cfg.tx.write = *dev->cfg.tx.read;
+	*dev->cfg.tx.state = cpu_to_le32(XSHM_OPEN);
+
+	if (parent_dev->ready_for_ipc)
+		err = xshmdev_ipc_tx(dev);
+
+	if (err < 0) {
+		xdev_dbg(dev, "can't update geno\n");
+		goto err;
+	}
+	/* If other side is ready as well we're ready to role */
+	if (*dev->cfg.rx.state == cpu_to_le32(XSHM_OPEN) &&
+			parent_dev->ready_for_ipc) {
+
+		if (do_open(dev) < 0)
+			goto err;
+		dev->state = XSHM_DEV_OPEN;
+	}
+
+	return 0;
+err:
+	pr_xshmstate(dev, "exit error");
+	*dev->cfg.rx.read = *dev->cfg.rx.write;
+	*dev->cfg.tx.write = *dev->cfg.tx.read;
+	*dev->cfg.tx.state = cpu_to_le32(XSHM_CLOSED);
+	return err;
+}
+
+static void xshmdev_close(struct xshm_dev *dev)
+{
+	pr_xshmstate(dev, "enter");
+
+	dev->state = XSHM_DEV_CLOSED;
+	*dev->cfg.rx.read = *dev->cfg.rx.write;
+	*dev->cfg.tx.state = cpu_to_le32(XSHM_CLOSED);
+	xshmdev_ipc_tx(dev);
+	if (dev->close_cb)
+		dev->close_cb(dev->driver_data);
+
+	xdev_vdbg(dev, "call genio_unsubscribe(%d)\n", dev->cfg.rx.xfer_bit);
+	genio_unsubscribe(dev->cfg.rx.xfer_bit);
+	xdev_vdbg(dev, "call genio_unsubscribe(%d)\n",
+			dev->cfg.tx.xfer_done_bit);
+	genio_unsubscribe(dev->cfg.tx.xfer_done_bit);
+}
+
+static void xshmdev_release(struct device *dev)
+{
+	struct xshm_dev *xshm = container_of(dev, struct xshm_dev, dev);
+	kfree(xshm);
+}
+
+int xshm_register_devices(struct xshm_channel *channel[], int channels)
+{
+
+	int i, err;
+	struct xshm_dev *dev;
+
+	for (i = 0; i < channels; i++) {
+		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+		if (dev == NULL)
+			return -ENOMEM;
+		dev_set_name(&dev->dev, "xshm%u", i);
+		dev->dev.release = xshmdev_release;
+
+		dev->state = XSHM_DEV_CLOSED;
+		dev->open = xshmdev_open;
+		dev->close = xshmdev_close;
+		dev->ipc_rx_release = xshmdev_ipc_rx_release;
+		dev->ipc_tx = xshmdev_ipc_tx;
+		xdev_vdbg(dev, "register XSHM device %s\n",
+				dev_name(&dev->dev));
+		dev->dev.parent = &parent_dev->dev;
+		dev->cfg = *channel[i];
+
+		err = xshm_register_device(dev);
+		if (err) {
+			xdev_dbg(dev, "registration failed (%d)\n", err);
+			return err;
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(xshm_register_devices);
+
+/* sysfs: ipc_ready file */
+static ssize_t caif_ready_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", parent_dev->ready_for_caif);
+}
+
+static DEVICE_ATTR(caif_ready, S_IRUSR | S_IRUGO, caif_ready_show, NULL);
+
+/* sysfs: notification on change of caif_ready to user space */
+void xshm_caif_ready(void)
+{
+	sysfs_notify(&parent_dev->dev.kobj, NULL,
+			dev_attr_caif_ready.attr.name);
+}
+
+/* sysfs: ipc_ready file */
+static ssize_t ipc_ready_show(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	return sprintf(buf, "%d\n", parent_dev->ready_for_ipc);
+}
+
+static DEVICE_ATTR(ipc_ready, S_IRUSR | S_IRUGO, ipc_ready_show, NULL);
+
+/* sysfs: notification on change of ipc_ready to user space */
+void xshm_ipc_ready(void)
+{
+	sysfs_notify(&parent_dev->dev.kobj, NULL, dev_attr_ipc_ready.attr.name);
+}
+
+static void genio_caif_ready_cb(bool ready)
+{
+	pr_devel("enter\n");
+	/* Set global variable ready_for_caif true */
+	if (parent_dev->ready_for_caif != ready) {
+		parent_dev->ready_for_caif = ready;
+		xshm_caif_ready();
+	}
+}
+
+static void genio_errhandler(int errno)
+{
+	/* Fake CAIF_READY low to trigger modem restart */
+	pr_warn("Driver reported error:%d\n", errno);
+	parent_dev->ready_for_caif = 0;
+	xshm_caif_ready();
+}
+
+struct xshm_bits {
+	u32 setter;
+	u32 getter;
+};
+
+static void collect_bits(struct xshm_dev *dev, void *data)
+{
+	struct xshm_bits *bits = data;
+	bits->setter |= 1 << dev->cfg.tx.xfer_bit;
+	bits->setter |= 1 << dev->cfg.rx.xfer_done_bit;
+	bits->getter |= 1 << dev->cfg.rx.xfer_bit;
+	bits->getter |= 1 << dev->cfg.tx.xfer_done_bit;
+}
+
+static void handle_open(struct xshm_dev *dev, void *data)
+{
+		if (dev->cfg.rx.state != NULL && dev->cfg.tx.state != NULL &&
+				*dev->cfg.rx.state == cpu_to_le32(XSHM_OPEN) &&
+				*dev->cfg.tx.state == cpu_to_le32(XSHM_OPEN)) {
+			dev->state = XSHM_DEV_OPEN;
+			do_open(dev);
+		}
+}
+
+void genio_ipc_ready_cb(void)
+{
+	int err;
+	struct xshm_bits bits = {0, 0};
+
+	pr_devel("enter\n");
+	/* Set global variable ready_for_ipc true */
+#ifdef DEBUG
+	/*
+	 * In real life ready_for_ipc doesn't change, but it's
+	 * convenient for testing.
+	 */
+	parent_dev->ready_for_ipc = !parent_dev->ready_for_ipc;
+#else
+	parent_dev->ready_for_ipc = true;
+#endif
+
+	xshm_ipc_ready();
+
+	genio_register_errhandler(genio_errhandler);
+
+	pr_devel("call genio_subscribe_caif_ready()\n");
+	err = genio_subscribe_caif_ready(genio_caif_ready_cb);
+	if (err < 0)
+		pr_debug("genio_subscribe_caif_ready failed:%d\n", err);
+
+	/* Collect the bit-mask for GENIO bits */
+	xshm_foreach_dev(collect_bits, &bits);
+	pr_devel("call genio_bit_alloc(%x,%x)\n", bits.setter, bits.getter);
+	err = genio_bit_alloc(bits.setter, bits.getter);
+	if (err < 0)
+		pr_debug("genio_bit_alloc failed:%d\n", err);
+	xshm_foreach_dev(handle_open, NULL);
+}
+EXPORT_SYMBOL(genio_ipc_ready_cb);
+
+int xshm_request_firmware(void *context, struct module *mod,
+		const char *img_name,
+		void (*cb)(const struct firmware *, void *))
+{
+	pr_debug("firmware request\n");
+	return request_firmware_nowait(mod,
+			FW_ACTION_NOHOTPLUG,
+			img_name,
+			&parent_dev->dev,
+			GFP_KERNEL,
+			context,
+			cb);
+}
+EXPORT_SYMBOL(xshm_request_firmware);
+
+static void parent_release(struct device *dev)
+{
+	struct xshm_parent *parent = container_of(dev, struct xshm_parent, dev);
+	WARN_ON(parent_dev != parent);
+	kfree(parent);
+	parent_dev = NULL;
+}
+
+static int __init xshm_init(void)
+{
+	int err;
+
+	pr_devel("Initializing\n");
+
+	parent_dev = kzalloc(sizeof(*parent_dev), GFP_KERNEL);
+	if (parent_dev  == NULL)
+		return -ENOMEM;
+
+	dev_set_name(&parent_dev->dev, "xshm");
+	parent_dev->dev.release = parent_release;
+
+	/* Pre-calculate inactivity timeout. */
+	if (xshm_inactivity_timeout != -1) {
+		parent_dev->inactivity_timeout =
+				xshm_inactivity_timeout * HZ / 1000;
+		if (parent_dev->inactivity_timeout == 0)
+			parent_dev->inactivity_timeout = 1;
+		else if (parent_dev->inactivity_timeout > NEXT_TIMER_MAX_DELTA)
+			parent_dev->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+	} else
+		parent_dev->inactivity_timeout = NEXT_TIMER_MAX_DELTA;
+
+	spin_lock_init(&parent_dev->timer_lock);
+	init_timer(&parent_dev->inactivity_timer);
+	parent_dev->inactivity_timer.data = 0L;
+	parent_dev->inactivity_timer.function = inactivity_tout;
+
+	err = device_register(&parent_dev->dev);
+	if (err)
+		goto err;
+
+	err = device_create_file(&parent_dev->dev, &dev_attr_ipc_ready);
+	if (err)
+		goto err_unreg;
+	err = device_create_file(&parent_dev->dev, &dev_attr_caif_ready);
+	if (err)
+		goto err_unreg;
+
+	return err;
+err_unreg:
+	pr_debug("initialization failed\n");
+	device_unregister(&parent_dev->dev);
+err:
+	return err;
+}
+
+static void handle_close(struct xshm_dev *dev, void *data)
+{
+	if (dev->close_cb)
+		dev->close_cb(dev->driver_data);
+}
+
+void close_devices(void)
+{
+	xshm_foreach_dev(handle_close, NULL);
+}
+
+static void handle_reset(struct xshm_dev *dev, void *data)
+{
+	if (dev->close_cb)
+		dev->close_cb(dev->driver_data);
+	xshm_unregister_device(dev);
+}
+
+void xshm_reset(void)
+{
+	parent_dev->ready_for_ipc = false;
+	parent_dev->ready_for_caif = false;
+	xshm_foreach_dev(handle_reset, NULL);
+	reset_activity_tout();
+	genio_reset();
+}
+EXPORT_SYMBOL(xshm_reset);
+
+static void __exit xshm_exit(void)
+{
+	xshm_reset();
+	device_unregister(&parent_dev->dev);
+	genio_unsubscribe(READY_FOR_IPC_BIT);
+	genio_unsubscribe(READY_FOR_CAIF_BIT);
+}
+
+module_init(xshm_init);
+module_exit(xshm_exit);
diff --git a/drivers/xshm/xshm_ipctoc.h b/drivers/xshm/xshm_ipctoc.h
new file mode 100644
index 0000000..b604bc5
--- /dev/null
+++ b/drivers/xshm/xshm_ipctoc.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef XSHM_TOC
+#define XSHM_TOC
+
+/**
+ * DOC: XSHM Shared Memory Layout
+ *
+ * XSHM defines a set of structures describing the memory layout used
+ * for the Shared Memory IPC. In short &toc_entry points out &ipc_toc,
+ * which points out the &xshm_ipctoc_channel. &xshm_ipctoc_channel defines
+ * the channels used to communicate between host and external device (modem).
+ *
+ *  &xshm_ipctoc_channel can be used in packet-mode or stream-mode,
+ *  and points out &xshm_bufidx holding information about cirular
+ *  buffers, andtheir read/write indices etc.
+ */
+
+struct _xshm_offsets {
+	__le32 rx;
+	__le32 tx;
+};
+
+/**
+ * struct xshm_ipctoc - Table Of Content definition for IPC.
+ *
+ * @magic:	Magic shall always be set to Ascii coded string "TC" (2 bytes)
+ * @version:	Main version of the TOC header.
+ * @subver:	Sub version of the TOC header.
+ * @channel_offsets: Offset to both rx and tx direction must be set.
+ *			The array must be terminated by a zero value.
+ *
+ * This struct is stored at the start of the External Shared memory, and
+ * serves as a extended table of contents defining the channel configurations
+ * for the external shared memory protocol between a modem and host.
+ *
+ * This extended table of content (ipctoc) is written to a predefine memory
+ * location and the modem will read this ipctoc during start-up and use this
+ * for setting up the IPC channels and it's buffers.
+ *
+ */
+
+struct xshm_ipctoc {
+	__u8 magic[2];
+	__u8 version;
+	__u8 subver;
+	struct _xshm_offsets channel_offsets[8];
+};
+
+#define XSHM_IPCTOC_MAGIC1 'T'
+#define XSHM_IPCTOC_MAGIC2 'C'
+
+/**
+ * struct xshm_ipctoc_channel - Channel descriptor for External Shared memory.
+ *
+ * @offset: Relative address to channel data area.
+ * @size: Total size of a SHM channel area partition.
+ * @mtu: Maximum Transfer Unit for packets in a buffer (packet mode).
+ * @packets: Maximum Number of packets in a buffer (packet mode).
+ * @mode: Mode of channel: Packet mode=1, Stream mode (shm_channel_mode = 2).
+ * @buffers: Number of buffers for the channel.
+ * @ipc: Offset to IPC message location (of type struct xshm_bufidx).
+ * @read_bit: GENI/O bit used to indicate update of the read pointer for
+ *	this channel (at offset ipc).
+ * @write_bit: GENI/O bit used to indicate update of the write pointer for
+ *	this channel (at offset ipc).
+ * @alignment: Protocol specific options for the protocol,
+ *	e.g. packet alignment.
+ *
+ * This struct defines the channel configuration for a single direction.
+ *
+ * This structure is pointed out by the &xshm_toc and is written by
+ * host during start-up and read by modem at firmware boot.
+ *
+ */
+
+struct xshm_ipctoc_channel {
+	__le32 offset;
+	__le32 size;
+/* private: */
+	__u8 unused[3];
+/* public: */
+	__u8 mode;
+	__le32 buffers;
+	__le32 ipc;
+	__le16 write_bit;
+	__le16 read_bit;
+	__u16 mtu;
+	__u8 packets;
+	__u8 alignment;
+};
+
+/**
+ * struct xshm_bufidx - Indices's for a uni-directional xshm channel.
+ *
+ * @read_index: Specify the read index for a channel. This field can
+ *	have value in range of [0.. xshm_ipctoc_channel.buffers -1].
+ *	In stream mode - this is the read index in the ringbuffer.
+ *	In packet mode - this index will at any time refer to the next
+ *	buffer available for read.
+ *
+ * @write_index: Specify the write index for a channel.
+ *	This field can have value in range of [0.. buffers -1].
+ *	In stream mode - this is the write index in the ringbuffer.
+ *	In packet mode - this index will at any time refer to the next
+ *	buffer available for write.
+ *
+ * @size: The actual number of bytes for a buffer at each index.
+ *	  This array has xshm_ipctoc_channel.buffers slots, one for each buffer.
+ *	  The size is updated every time data is written to the buffer.
+ *
+ * @state: The state of the channel, 0 - Closed, 1 - Open
+ *
+ *
+ * This structure contains data for the ring-buffer used in packet and stream
+ * mode, for the external shared memory protocol.
+ * Note that the read_buf_index and the write_buf_index
+ * refer to two different channels. So for a ring buffer used to communicate
+ * from modem, the modem will update the write_buf_index while Linux host
+ * will update read_buf_index.
+ */
+struct xshm_bufidx {
+	__le32 state;
+	__le32 read_index;
+	__le32 write_index;
+	__le32 size[0];
+};
+
+/** struct toc_entry - Points out the boot imiages
+ *
+ * @start: Offset counting from start of memory area to the image data.
+ * @size:  Size of the images in bytes.
+ * @flags: Use 0 if no flags are in use.
+ * @entry: Where to jump to start exeuting. Only applicable
+ *		when using SDRAM. Set to 0xffffffff if unused.
+ * @load_addr: Location in SDRAM to move image. Set to 0xffffffff if
+ *		not applicable.
+ * @name: Name of image.
+ */
+struct toc_entry {
+	__le32 start;
+	__le32 size;
+	__le32 flags;
+	__le32 entry_point;
+	__le32 load_addr;
+	char name[12];
+};
+
+#endif
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 2f213d1..b960ff0 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -365,10 +365,10 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
 		_debug("extract data");
 		if (call->count > 0) {
 			page = call->reply3;
-			buffer = kmap_atomic(page, KM_USER0);
+			buffer = kmap_atomic(page);
 			ret = afs_extract_data(call, skb, last, buffer,
 					       call->count);
-			kunmap_atomic(buffer, KM_USER0);
+			kunmap_atomic(buffer);
 			switch (ret) {
 			case 0:		break;
 			case -EAGAIN:	return 0;
@@ -411,9 +411,9 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
 	if (call->count < PAGE_SIZE) {
 		_debug("clear");
 		page = call->reply3;
-		buffer = kmap_atomic(page, KM_USER0);
+		buffer = kmap_atomic(page);
 		memset(buffer + call->count, 0, PAGE_SIZE - call->count);
-		kunmap_atomic(buffer, KM_USER0);
+		kunmap_atomic(buffer);
 	}
 
 	_leave(" = 0 [done]");
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 8f4ce26..298cf89 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -200,9 +200,9 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
 		if (PageError(page))
 			goto error;
 
-		buf = kmap_atomic(page, KM_USER0);
+		buf = kmap_atomic(page);
 		memcpy(devname, buf, size);
-		kunmap_atomic(buf, KM_USER0);
+		kunmap_atomic(buf);
 		page_cache_release(page);
 		page = NULL;
 	}
diff --git a/fs/aio.c b/fs/aio.c
index 969beb0..04ae7e2 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -160,7 +160,7 @@ static int aio_setup_ring(struct kioctx *ctx)
 
 	info->nr = nr_events;		/* trusted copy */
 
-	ring = kmap_atomic(info->ring_pages[0], KM_USER0);
+	ring = kmap_atomic(info->ring_pages[0]);
 	ring->nr = nr_events;	/* user copy */
 	ring->id = ctx->user_id;
 	ring->head = ring->tail = 0;
@@ -168,32 +168,32 @@ static int aio_setup_ring(struct kioctx *ctx)
 	ring->compat_features = AIO_RING_COMPAT_FEATURES;
 	ring->incompat_features = AIO_RING_INCOMPAT_FEATURES;
 	ring->header_length = sizeof(struct aio_ring);
-	kunmap_atomic(ring, KM_USER0);
+	kunmap_atomic(ring);
 
 	return 0;
 }
 
 
 /* aio_ring_event: returns a pointer to the event at the given index from
- * kmap_atomic(, km).  Release the pointer with put_aio_ring_event();
+ * kmap_atomic().  Release the pointer with put_aio_ring_event();
  */
 #define AIO_EVENTS_PER_PAGE	(PAGE_SIZE / sizeof(struct io_event))
 #define AIO_EVENTS_FIRST_PAGE	((PAGE_SIZE - sizeof(struct aio_ring)) / sizeof(struct io_event))
 #define AIO_EVENTS_OFFSET	(AIO_EVENTS_PER_PAGE - AIO_EVENTS_FIRST_PAGE)
 
-#define aio_ring_event(info, nr, km) ({					\
+#define aio_ring_event(info, nr) ({					\
 	unsigned pos = (nr) + AIO_EVENTS_OFFSET;			\
 	struct io_event *__event;					\
 	__event = kmap_atomic(						\
-			(info)->ring_pages[pos / AIO_EVENTS_PER_PAGE], km); \
+			(info)->ring_pages[pos / AIO_EVENTS_PER_PAGE]); \
 	__event += pos % AIO_EVENTS_PER_PAGE;				\
 	__event;							\
 })
 
-#define put_aio_ring_event(event, km) do {	\
+#define put_aio_ring_event(event) do {		\
 	struct io_event *__event = (event);	\
 	(void)__event;				\
-	kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK), km); \
+	kunmap_atomic((void *)((unsigned long)__event & PAGE_MASK)); \
 } while(0)
 
 static void ctx_rcu_free(struct rcu_head *head)
@@ -1019,10 +1019,10 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
 	if (kiocbIsCancelled(iocb))
 		goto put_rq;
 
-	ring = kmap_atomic(info->ring_pages[0], KM_IRQ1);
+	ring = kmap_atomic(info->ring_pages[0]);
 
 	tail = info->tail;
-	event = aio_ring_event(info, tail, KM_IRQ0);
+	event = aio_ring_event(info, tail);
 	if (++tail >= info->nr)
 		tail = 0;
 
@@ -1043,8 +1043,8 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
 	info->tail = tail;
 	ring->tail = tail;
 
-	put_aio_ring_event(event, KM_IRQ0);
-	kunmap_atomic(ring, KM_IRQ1);
+	put_aio_ring_event(event);
+	kunmap_atomic(ring);
 
 	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
@@ -1089,7 +1089,7 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent)
 	unsigned long head;
 	int ret = 0;
 
-	ring = kmap_atomic(info->ring_pages[0], KM_USER0);
+	ring = kmap_atomic(info->ring_pages[0]);
 	dprintk("in aio_read_evt h%lu t%lu m%lu\n",
 		 (unsigned long)ring->head, (unsigned long)ring->tail,
 		 (unsigned long)ring->nr);
@@ -1101,18 +1101,18 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent)
 
 	head = ring->head % info->nr;
 	if (head != ring->tail) {
-		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
+		struct io_event *evp = aio_ring_event(info, head);
 		*ent = *evp;
 		head = (head + 1) % info->nr;
 		smp_mb(); /* finish reading the event before updatng the head */
 		ring->head = head;
 		ret = 1;
-		put_aio_ring_event(evp, KM_USER1);
+		put_aio_ring_event(evp);
 	}
 	spin_unlock(&info->ring_lock);
 
 out:
-	kunmap_atomic(ring, KM_USER0);
+	kunmap_atomic(ring);
 	dprintk("leaving aio_read_evt: %d  h%lu t%lu\n", ret,
 		 (unsigned long)ring->head, (unsigned long)ring->tail);
 	return ret;
diff --git a/fs/attr.c b/fs/attr.c
index 95053ad..ff3746f 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -171,11 +171,18 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 	struct timespec now;
 	unsigned int ia_valid = attr->ia_valid;
 
+	WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
+
 	if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
 		if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 			return -EPERM;
 	}
 
+	if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) {
+		if (attr->ia_size != inode->i_size)
+			inode_inc_iversion(inode);
+	}
+
 	if ((ia_valid & ATTR_MODE)) {
 		umode_t amode = attr->ia_mode;
 		/* Flag setting protected by i_mutex */
@@ -245,5 +252,4 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 
 	return error;
 }
-
 EXPORT_SYMBOL(notify_change);
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c
index c2183f3..e85c04b 100644
--- a/fs/bio-integrity.c
+++ b/fs/bio-integrity.c
@@ -357,7 +357,7 @@ static void bio_integrity_generate(struct bio *bio)
 	bix.sector_size = bi->sector_size;
 
 	bio_for_each_segment(bv, bio, i) {
-		void *kaddr = kmap_atomic(bv->bv_page, KM_USER0);
+		void *kaddr = kmap_atomic(bv->bv_page);
 		bix.data_buf = kaddr + bv->bv_offset;
 		bix.data_size = bv->bv_len;
 		bix.prot_buf = prot_buf;
@@ -371,7 +371,7 @@ static void bio_integrity_generate(struct bio *bio)
 		total += sectors * bi->tuple_size;
 		BUG_ON(total > bio->bi_integrity->bip_size);
 
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 }
 
@@ -498,7 +498,7 @@ static int bio_integrity_verify(struct bio *bio)
 	bix.sector_size = bi->sector_size;
 
 	bio_for_each_segment(bv, bio, i) {
-		void *kaddr = kmap_atomic(bv->bv_page, KM_USER0);
+		void *kaddr = kmap_atomic(bv->bv_page);
 		bix.data_buf = kaddr + bv->bv_offset;
 		bix.data_size = bv->bv_len;
 		bix.prot_buf = prot_buf;
@@ -507,7 +507,7 @@ static int bio_integrity_verify(struct bio *bio)
 		ret = bi->verify_fn(&bix);
 
 		if (ret) {
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			return ret;
 		}
 
@@ -517,7 +517,7 @@ static int bio_integrity_verify(struct bio *bio)
 		total += sectors * bi->tuple_size;
 		BUG_ON(total > bio->bi_integrity->bip_size);
 
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 
 	return ret;
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 14f1c5a..93f4af1 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -120,10 +120,10 @@ static int check_compressed_csum(struct inode *inode,
 		page = cb->compressed_pages[i];
 		csum = ~(u32)0;
 
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		csum = btrfs_csum_data(root, kaddr, csum, PAGE_CACHE_SIZE);
 		btrfs_csum_final(csum, (char *)&csum);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 
 		if (csum != *cb_sum) {
 			printk(KERN_INFO "btrfs csum failed ino %llu "
@@ -521,10 +521,10 @@ static noinline int add_ra_bio_pages(struct inode *inode,
 			if (zero_offset) {
 				int zeros;
 				zeros = PAGE_CACHE_SIZE - zero_offset;
-				userpage = kmap_atomic(page, KM_USER0);
+				userpage = kmap_atomic(page);
 				memset(userpage + zero_offset, 0, zeros);
 				flush_dcache_page(page);
-				kunmap_atomic(userpage, KM_USER0);
+				kunmap_atomic(userpage);
 			}
 		}
 
@@ -991,9 +991,9 @@ int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
 		bytes = min(PAGE_CACHE_SIZE - *pg_offset,
 			    PAGE_CACHE_SIZE - buf_offset);
 		bytes = min(bytes, working_bytes);
-		kaddr = kmap_atomic(page_out, KM_USER0);
+		kaddr = kmap_atomic(page_out);
 		memcpy(kaddr + *pg_offset, buf + buf_offset, bytes);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		flush_dcache_page(page_out);
 
 		*pg_offset += bytes;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 9d09a4f..6c062c7 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2535,10 +2535,10 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
 
 		if (zero_offset) {
 			iosize = PAGE_CACHE_SIZE - zero_offset;
-			userpage = kmap_atomic(page, KM_USER0);
+			userpage = kmap_atomic(page);
 			memset(userpage + zero_offset, 0, iosize);
 			flush_dcache_page(page);
-			kunmap_atomic(userpage, KM_USER0);
+			kunmap_atomic(userpage);
 		}
 	}
 	while (cur <= end) {
@@ -2547,10 +2547,10 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
 			struct extent_state *cached = NULL;
 
 			iosize = PAGE_CACHE_SIZE - pg_offset;
-			userpage = kmap_atomic(page, KM_USER0);
+			userpage = kmap_atomic(page);
 			memset(userpage + pg_offset, 0, iosize);
 			flush_dcache_page(page);
-			kunmap_atomic(userpage, KM_USER0);
+			kunmap_atomic(userpage);
 			set_extent_uptodate(tree, cur, cur + iosize - 1,
 					    &cached, GFP_NOFS);
 			unlock_extent_cached(tree, cur, cur + iosize - 1,
@@ -2596,10 +2596,10 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
 			char *userpage;
 			struct extent_state *cached = NULL;
 
-			userpage = kmap_atomic(page, KM_USER0);
+			userpage = kmap_atomic(page);
 			memset(userpage + pg_offset, 0, iosize);
 			flush_dcache_page(page);
-			kunmap_atomic(userpage, KM_USER0);
+			kunmap_atomic(userpage);
 
 			set_extent_uptodate(tree, cur, cur + iosize - 1,
 					    &cached, GFP_NOFS);
@@ -2745,10 +2745,10 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
 	if (page->index == end_index) {
 		char *userpage;
 
-		userpage = kmap_atomic(page, KM_USER0);
+		userpage = kmap_atomic(page);
 		memset(userpage + pg_offset, 0,
 		       PAGE_CACHE_SIZE - pg_offset);
-		kunmap_atomic(userpage, KM_USER0);
+		kunmap_atomic(userpage);
 		flush_dcache_page(page);
 	}
 	pg_offset = 0;
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index c7fb3a4..078b4fd 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -447,13 +447,13 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
 			sums->bytenr = ordered->start;
 		}
 
-		data = kmap_atomic(bvec->bv_page, KM_USER0);
+		data = kmap_atomic(bvec->bv_page);
 		sector_sum->sum = ~(u32)0;
 		sector_sum->sum = btrfs_csum_data(root,
 						  data + bvec->bv_offset,
 						  sector_sum->sum,
 						  bvec->bv_len);
-		kunmap_atomic(data, KM_USER0);
+		kunmap_atomic(data);
 		btrfs_csum_final(sector_sum->sum,
 				 (char *)&sector_sum->sum);
 		sector_sum->bytenr = disk_bytenr;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0da19a0..d2f5df0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -173,9 +173,9 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
 			cur_size = min_t(unsigned long, compressed_size,
 				       PAGE_CACHE_SIZE);
 
-			kaddr = kmap_atomic(cpage, KM_USER0);
+			kaddr = kmap_atomic(cpage);
 			write_extent_buffer(leaf, kaddr, ptr, cur_size);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 
 			i++;
 			ptr += cur_size;
@@ -187,10 +187,10 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
 		page = find_get_page(inode->i_mapping,
 				     start >> PAGE_CACHE_SHIFT);
 		btrfs_set_file_extent_compression(leaf, ei, 0);
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		offset = start & (PAGE_CACHE_SIZE - 1);
 		write_extent_buffer(leaf, kaddr + offset, ptr, size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		page_cache_release(page);
 	}
 	btrfs_mark_buffer_dirty(leaf);
@@ -422,10 +422,10 @@ again:
 			 * sending it down to disk
 			 */
 			if (offset) {
-				kaddr = kmap_atomic(page, KM_USER0);
+				kaddr = kmap_atomic(page);
 				memset(kaddr + offset, 0,
 				       PAGE_CACHE_SIZE - offset);
-				kunmap_atomic(kaddr, KM_USER0);
+				kunmap_atomic(kaddr);
 			}
 			will_compress = 1;
 		}
@@ -1863,7 +1863,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 	} else {
 		ret = get_state_private(io_tree, start, &private);
 	}
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (ret)
 		goto zeroit;
 
@@ -1872,7 +1872,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
 	if (csum != private)
 		goto zeroit;
 
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 good:
 	return 0;
 
@@ -1884,7 +1884,7 @@ zeroit:
 		       (unsigned long long)private);
 	memset(kaddr + offset, 1, end - start + 1);
 	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	if (private == 0)
 		return 0;
 	return -EIO;
@@ -4909,12 +4909,12 @@ static noinline int uncompress_inline(struct btrfs_path *path,
 	ret = btrfs_decompress(compress_type, tmp, page,
 			       extent_offset, inline_size, max_size);
 	if (ret) {
-		char *kaddr = kmap_atomic(page, KM_USER0);
+		char *kaddr = kmap_atomic(page);
 		unsigned long copy_size = min_t(u64,
 				  PAGE_CACHE_SIZE - pg_offset,
 				  max_size - extent_offset);
 		memset(kaddr + pg_offset, 0, copy_size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 	kfree(tmp);
 	return 0;
@@ -5691,11 +5691,11 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
 			unsigned long flags;
 
 			local_irq_save(flags);
-			kaddr = kmap_atomic(page, KM_IRQ0);
+			kaddr = kmap_atomic(page);
 			csum = btrfs_csum_data(root, kaddr + bvec->bv_offset,
 					       csum, bvec->bv_len);
 			btrfs_csum_final(csum, (char *)&csum);
-			kunmap_atomic(kaddr, KM_IRQ0);
+			kunmap_atomic(kaddr);
 			local_irq_restore(flags);
 
 			flush_dcache_page(bvec->bv_page);
diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
index a178f5e..743b86f 100644
--- a/fs/btrfs/lzo.c
+++ b/fs/btrfs/lzo.c
@@ -411,9 +411,9 @@ static int lzo_decompress(struct list_head *ws, unsigned char *data_in,
 
 	bytes = min_t(unsigned long, destlen, out_len - start_byte);
 
-	kaddr = kmap_atomic(dest_page, KM_USER0);
+	kaddr = kmap_atomic(dest_page);
 	memcpy(kaddr, workspace->buf + start_byte, bytes);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 out:
 	return ret;
 }
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 9770cc5..1867109 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -591,7 +591,7 @@ static int scrub_fixup_check(struct scrub_bio *sbio, int ix)
 	u64 flags = sbio->spag[ix].flags;
 
 	page = sbio->bio->bi_io_vec[ix].bv_page;
-	buffer = kmap_atomic(page, KM_USER0);
+	buffer = kmap_atomic(page);
 	if (flags & BTRFS_EXTENT_FLAG_DATA) {
 		ret = scrub_checksum_data(sbio->sdev,
 					  sbio->spag + ix, buffer);
@@ -603,7 +603,7 @@ static int scrub_fixup_check(struct scrub_bio *sbio, int ix)
 	} else {
 		WARN_ON(1);
 	}
-	kunmap_atomic(buffer, KM_USER0);
+	kunmap_atomic(buffer);
 
 	return ret;
 }
@@ -792,7 +792,7 @@ static void scrub_checksum(struct btrfs_work *work)
 	}
 	for (i = 0; i < sbio->count; ++i) {
 		page = sbio->bio->bi_io_vec[i].bv_page;
-		buffer = kmap_atomic(page, KM_USER0);
+		buffer = kmap_atomic(page);
 		flags = sbio->spag[i].flags;
 		logical = sbio->logical + i * PAGE_SIZE;
 		ret = 0;
@@ -807,7 +807,7 @@ static void scrub_checksum(struct btrfs_work *work)
 		} else {
 			WARN_ON(1);
 		}
-		kunmap_atomic(buffer, KM_USER0);
+		kunmap_atomic(buffer);
 		if (ret) {
 			ret = scrub_recheck_error(sbio, i);
 			if (!ret) {
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
index faccd47..92c2065 100644
--- a/fs/btrfs/zlib.c
+++ b/fs/btrfs/zlib.c
@@ -370,9 +370,9 @@ static int zlib_decompress(struct list_head *ws, unsigned char *data_in,
 			    PAGE_CACHE_SIZE - buf_offset);
 		bytes = min(bytes, bytes_left);
 
-		kaddr = kmap_atomic(dest_page, KM_USER0);
+		kaddr = kmap_atomic(dest_page);
 		memcpy(kaddr + pg_offset, workspace->buf + buf_offset, bytes);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 
 		pg_offset += bytes;
 		bytes_left -= bytes;
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index a0358c2..3f45831 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/fsnotify.h>
 #include <linux/quotaops.h>
 #include <linux/xattr.h>
 #include <linux/mount.h>
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index e18b183..6e05068 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/fs.h>
-#include <linux/fsnotify.h>
 #include <linux/quotaops.h>
 #include <linux/xattr.h>
 #include <linux/slab.h>
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index f66cc16..0554b00 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -140,7 +140,6 @@ config CIFS_DFS_UPCALL
 
 config CIFS_FSCACHE
 	  bool "Provide CIFS client caching support (EXPERIMENTAL)"
-	  depends on EXPERIMENTAL
 	  depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
 	  help
 	    Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
@@ -149,7 +148,7 @@ config CIFS_FSCACHE
 
 config CIFS_ACL
 	  bool "Provide CIFS ACL support (EXPERIMENTAL)"
-	  depends on EXPERIMENTAL && CIFS_XATTR && KEYS
+	  depends on CIFS_XATTR && KEYS
 	  help
 	    Allows to fetch CIFS/NTFS ACL from the server.  The DACL blob
 	    is handed over to the application/caller.
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 84e8c07..24b3dfc 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -676,14 +676,23 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file,
 {
 	char c;
 	int rc;
+	static bool warned;
 
 	rc = get_user(c, buffer);
 	if (rc)
 		return rc;
 	if (c == '0' || c == 'n' || c == 'N')
 		multiuser_mount = 0;
-	else if (c == '1' || c == 'y' || c == 'Y')
+	else if (c == '1' || c == 'y' || c == 'Y') {
 		multiuser_mount = 1;
+		if (!warned) {
+			warned = true;
+			printk(KERN_WARNING "CIFS VFS: The legacy multiuser "
+				"mount code is scheduled to be deprecated in "
+				"3.5. Please switch to using the multiuser "
+				"mount option.");
+		}
+	}
 
 	return count;
 }
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c
index 2272fd5..e622863 100644
--- a/fs/cifs/cifs_spnego.c
+++ b/fs/cifs/cifs_spnego.c
@@ -113,9 +113,11 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
 		   MAX_MECH_STR_LEN +
 		   UID_KEY_LEN + (sizeof(uid_t) * 2) +
 		   CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
-		   USER_KEY_LEN + strlen(sesInfo->user_name) +
 		   PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 
+	if (sesInfo->user_name)
+		desc_len += USER_KEY_LEN + strlen(sesInfo->user_name);
+
 	spnego_key = ERR_PTR(-ENOMEM);
 	description = kzalloc(desc_len, GFP_KERNEL);
 	if (description == NULL)
@@ -152,8 +154,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
 	dp = description + strlen(description);
 	sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
 
-	dp = description + strlen(description);
-	sprintf(dp, ";user=%s", sesInfo->user_name);
+	if (sesInfo->user_name) {
+		dp = description + strlen(description);
+		sprintf(dp, ";user=%s", sesInfo->user_name);
+	}
 
 	dp = description + strlen(description);
 	sprintf(dp, ";pid=0x%x", current->pid);
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 1b2e180..fbb9da9 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -27,17 +27,17 @@
 #include "cifs_debug.h"
 
 /*
- * cifs_ucs2_bytes - how long will a string be after conversion?
- * @ucs - pointer to input string
+ * cifs_utf16_bytes - how long will a string be after conversion?
+ * @utf16 - pointer to input string
  * @maxbytes - don't go past this many bytes of input string
  * @codepage - destination codepage
  *
- * Walk a ucs2le string and return the number of bytes that the string will
+ * Walk a utf16le string and return the number of bytes that the string will
  * be after being converted to the given charset, not including any null
  * termination required. Don't walk past maxbytes in the source buffer.
  */
 int
-cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+cifs_utf16_bytes(const __le16 *from, int maxbytes,
 		const struct nls_table *codepage)
 {
 	int i;
@@ -122,7 +122,7 @@ cp_convert:
 }
 
 /*
- * cifs_from_ucs2 - convert utf16le string to local charset
+ * cifs_from_utf16 - convert utf16le string to local charset
  * @to - destination buffer
  * @from - source buffer
  * @tolen - destination buffer size (in bytes)
@@ -130,7 +130,7 @@ cp_convert:
  * @codepage - codepage to which characters should be converted
  * @mapchar - should characters be remapped according to the mapchars option?
  *
- * Convert a little-endian ucs2le string (as sent by the server) to a string
+ * Convert a little-endian utf16le string (as sent by the server) to a string
  * in the provided codepage. The tolen and fromlen parameters are to ensure
  * that the code doesn't walk off of the end of the buffer (which is always
  * a danger if the alignment of the source buffer is off). The destination
@@ -139,12 +139,12 @@ cp_convert:
  * null terminator).
  *
  * Note that some windows versions actually send multiword UTF-16 characters
- * instead of straight UCS-2. The linux nls routines however aren't able to
+ * instead of straight UTF16-2. The linux nls routines however aren't able to
  * deal with those characters properly. In the event that we get some of
  * those characters, they won't be translated properly.
  */
 int
-cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
 		 const struct nls_table *codepage, bool mapchar)
 {
 	int i, charlen, safelen;
@@ -190,13 +190,13 @@ cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
 }
 
 /*
- * NAME:	cifs_strtoUCS()
+ * NAME:	cifs_strtoUTF16()
  *
  * FUNCTION:	Convert character string to unicode string
  *
  */
 int
-cifs_strtoUCS(__le16 *to, const char *from, int len,
+cifs_strtoUTF16(__le16 *to, const char *from, int len,
 	      const struct nls_table *codepage)
 {
 	int charlen;
@@ -206,7 +206,7 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
 	for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
 		charlen = codepage->char2uni(from, len, &wchar_to);
 		if (charlen < 1) {
-			cERROR(1, "strtoUCS: char2uni of 0x%x returned %d",
+			cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d",
 				*from, charlen);
 			/* A question mark */
 			wchar_to = 0x003f;
@@ -220,7 +220,8 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
 }
 
 /*
- * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
+ * cifs_strndup_from_utf16 - copy a string from wire format to the local
+ * codepage
  * @src - source string
  * @maxlen - don't walk past this many bytes in the source string
  * @is_unicode - is this a unicode string?
@@ -231,19 +232,19 @@ cifs_strtoUCS(__le16 *to, const char *from, int len,
  * error.
  */
 char *
-cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
-	     const struct nls_table *codepage)
+cifs_strndup_from_utf16(const char *src, const int maxlen,
+			const bool is_unicode, const struct nls_table *codepage)
 {
 	int len;
 	char *dst;
 
 	if (is_unicode) {
-		len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+		len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage);
 		len += nls_nullsize(codepage);
 		dst = kmalloc(len, GFP_KERNEL);
 		if (!dst)
 			return NULL;
-		cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+		cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage,
 			       false);
 	} else {
 		len = strnlen(src, maxlen);
@@ -264,7 +265,7 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
  * names are little endian 16 bit Unicode on the wire
  */
 int
-cifsConvertToUCS(__le16 *target, const char *source, int srclen,
+cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
 		 const struct nls_table *cp, int mapChars)
 {
 	int i, j, charlen;
@@ -273,7 +274,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 	wchar_t tmp;
 
 	if (!mapChars)
-		return cifs_strtoUCS(target, source, PATH_MAX, cp);
+		return cifs_strtoUTF16(target, source, PATH_MAX, cp);
 
 	for (i = 0, j = 0; i < srclen; j++) {
 		src_char = source[i];
@@ -281,7 +282,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 		switch (src_char) {
 		case 0:
 			put_unaligned(0, &target[j]);
-			goto ctoUCS_out;
+			goto ctoUTF16_out;
 		case ':':
 			dst_char = cpu_to_le16(UNI_COLON);
 			break;
@@ -326,7 +327,7 @@ cifsConvertToUCS(__le16 *target, const char *source, int srclen,
 		put_unaligned(dst_char, &target[j]);
 	}
 
-ctoUCS_out:
+ctoUTF16_out:
 	return i;
 }
 
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index 6d02fd5..a513a54 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[];
 #endif				/* UNIUPR_NOLOWER */
 
 #ifdef __KERNEL__
-int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
-		   const struct nls_table *codepage, bool mapchar);
-int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
-		    const struct nls_table *codepage);
-int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
-char *cifs_strndup_from_ucs(const char *src, const int maxlen,
-			    const bool is_unicode,
-			    const struct nls_table *codepage);
-extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
-			const struct nls_table *cp, int mapChars);
+int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen,
+		    const struct nls_table *codepage, bool mapchar);
+int cifs_utf16_bytes(const __le16 *from, int maxbytes,
+		     const struct nls_table *codepage);
+int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_utf16(const char *src, const int maxlen,
+			      const bool is_unicode,
+			      const struct nls_table *codepage);
+extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen,
+			      const struct nls_table *cp, int mapChars);
 
 #endif
 
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 72ddf23..c1b2544 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -909,6 +909,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 		umode_t group_mask = S_IRWXG;
 		umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 
+		if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
+			return;
 		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
 				GFP_KERNEL);
 		if (!ppace) {
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5d9b9ac..63c460e 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -327,7 +327,7 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp)
 	attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME);
 	attrptr->length = cpu_to_le16(2 * dlen);
 	blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name);
-	cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
+	cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp);
 
 	return 0;
 }
@@ -376,7 +376,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp)
 					kmalloc(attrsize + 1, GFP_KERNEL);
 				if (!ses->domainName)
 						return -ENOMEM;
-				cifs_from_ucs2(ses->domainName,
+				cifs_from_utf16(ses->domainName,
 					(__le16 *)blobptr, attrsize, attrsize,
 					nls_cp, false);
 				break;
@@ -420,15 +420,20 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 	}
 
 	/* convert ses->user_name to unicode and uppercase */
-	len = strlen(ses->user_name);
+	len = ses->user_name ? strlen(ses->user_name) : 0;
 	user = kmalloc(2 + (len * 2), GFP_KERNEL);
 	if (user == NULL) {
 		cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
 		rc = -ENOMEM;
 		return rc;
 	}
-	len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
-	UniStrupr(user);
+
+	if (len) {
+		len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp);
+		UniStrupr(user);
+	} else {
+		memset(user, '\0', 2);
+	}
 
 	rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 				(char *)user, 2 * len);
@@ -448,8 +453,8 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 			rc = -ENOMEM;
 			return rc;
 		}
-		len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
-					nls_cp);
+		len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len,
+				      nls_cp);
 		rc =
 		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
 					(char *)domain, 2 * len);
@@ -468,7 +473,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
 			rc = -ENOMEM;
 			return rc;
 		}
-		len = cifs_strtoUCS((__le16 *)server, ses->serverName, len,
+		len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len,
 					nls_cp);
 		rc =
 		crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index b1fd382..d81cbba 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -703,7 +703,7 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 	 * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate
 	 * the cached file length
 	 */
-	if (origin != SEEK_SET || origin != SEEK_CUR) {
+	if (origin != SEEK_SET && origin != SEEK_CUR) {
 		int rc;
 		struct inode *inode = file->f_path.dentry->d_inode;
 
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ba53c1c..76e7d8b 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -879,6 +879,8 @@ require use of the stronger protocol */
 #define   CIFSSEC_MASK          0xB70B7 /* current flags supported if weak */
 #endif /* UPCALL */
 #else /* do not allow weak pw hash */
+#define   CIFSSEC_MUST_LANMAN	0
+#define   CIFSSEC_MUST_PLNTXT	0
 #ifdef CONFIG_CIFS_UPCALL
 #define   CIFSSEC_MASK          0x8F08F /* flags supported if no weak allowed */
 #else
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 6600aa2..8b7794c 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -821,8 +821,8 @@ PsxDelete:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else { /* BB add path length overrun check */
@@ -893,8 +893,8 @@ DelFileRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve check for buffer overruns BB */
@@ -938,8 +938,8 @@ RmDirRetry:
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
-					 PATH_MAX, nls_codepage, remap);
+		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName,
+					      PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve check for buffer overruns BB */
@@ -981,8 +981,8 @@ MkDirRetry:
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
-					    PATH_MAX, nls_codepage, remap);
+		name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name,
+					      PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {		/* BB improve check for buffer overruns BB */
@@ -1030,8 +1030,8 @@ PsxCreat:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, name,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, name,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -1197,8 +1197,8 @@ OldOpenRetry:
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		count = 1;      /* account for one byte pad to word boundary */
 		name_len =
-		   cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
-				    fileName, PATH_MAX, nls_codepage, remap);
+		   cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+				      fileName, PATH_MAX, nls_codepage, remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {                /* BB improve check for buffer overruns BB */
@@ -1304,8 +1304,8 @@ openRetry:
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		count = 1;	/* account for one byte pad to word boundary */
 		name_len =
-		    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
-				     fileName, PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1),
+				       fileName, PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 		pSMB->NameLength = cpu_to_le16(name_len);
@@ -2649,16 +2649,16 @@ renameRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 		pSMB->OldFileName[name_len] = 0x04;	/* pad */
 	/* protocol requires ASCII signature byte on Unicode string */
 		pSMB->OldFileName[name_len + 1] = 0x00;
 		name_len2 =
-		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-				     toName, PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+				       toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -2738,10 +2738,12 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon,
 	/* unicode only call */
 	if (target_name == NULL) {
 		sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid);
-		len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+		len_of_str =
+			cifsConvertToUTF16((__le16 *)rename_info->target_name,
 					dummy_string, 24, nls_codepage, remap);
 	} else {
-		len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+		len_of_str =
+			cifsConvertToUTF16((__le16 *)rename_info->target_name,
 					target_name, PATH_MAX, nls_codepage,
 					remap);
 	}
@@ -2795,17 +2797,17 @@ copyRetry:
 	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
-					    fromName, PATH_MAX, nls_codepage,
-					    remap);
+		name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName,
+					      fromName, PATH_MAX, nls_codepage,
+					      remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 		pSMB->OldFileName[name_len] = 0x04;     /* pad */
 		/* protocol requires ASCII signature byte on Unicode string */
 		pSMB->OldFileName[name_len + 1] = 0x00;
 		name_len2 =
-		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-				toName, PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+				       toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2; /* convert to bytes */
 	} else { 	/* BB improve the check for buffer overruns BB */
@@ -2861,9 +2863,9 @@ createSymLinkRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName,
+				    /* find define for this maxpathcomponent */
+				    PATH_MAX, nls_codepage);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 
@@ -2885,9 +2887,9 @@ createSymLinkRetry:
 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
-		    cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
-				  /* find define for this maxpathcomponent */
-				  , nls_codepage);
+		    cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX
+				    /* find define for this maxpathcomponent */
+				    , nls_codepage);
 		name_len_target++;	/* trailing null */
 		name_len_target *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -2949,8 +2951,8 @@ createHardLinkRetry:
 		return rc;
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
-					    PATH_MAX, nls_codepage, remap);
+		name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName,
+					      PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 
@@ -2972,8 +2974,8 @@ createHardLinkRetry:
 	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
-		    cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
-				     nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) data_offset, fromName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len_target++;	/* trailing null */
 		name_len_target *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -3042,8 +3044,8 @@ winCreateHardLinkRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 
@@ -3051,8 +3053,8 @@ winCreateHardLinkRetry:
 		pSMB->OldFileName[name_len] = 0x04;
 		pSMB->OldFileName[name_len + 1] = 0x00; /* pad */
 		name_len2 =
-		    cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
-				     toName, PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2],
+				       toName, PATH_MAX, nls_codepage, remap);
 		name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
 		name_len2 *= 2;	/* convert to bytes */
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -3108,8 +3110,8 @@ querySymLinkRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifs_strtoUCS((__le16 *) pSMB->FileName, searchName,
-				  PATH_MAX, nls_codepage);
+			cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName,
+					PATH_MAX, nls_codepage);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -3166,8 +3168,8 @@ querySymLinkRetry:
 				is_unicode = false;
 
 			/* BB FIXME investigate remapping reserved chars here */
-			*symlinkinfo = cifs_strndup_from_ucs(data_start, count,
-						    is_unicode, nls_codepage);
+			*symlinkinfo = cifs_strndup_from_utf16(data_start,
+					count, is_unicode, nls_codepage);
 			if (!*symlinkinfo)
 				rc = -ENOMEM;
 		}
@@ -3450,8 +3452,9 @@ queryAclRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-					 PATH_MAX, nls_codepage, remap);
+			cifsConvertToUTF16((__le16 *) pSMB->FileName,
+					   searchName, PATH_MAX, nls_codepage,
+					   remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 		pSMB->FileName[name_len] = 0;
@@ -3537,8 +3540,8 @@ setAclRetry:
 		return rc;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				      PATH_MAX, nls_codepage, remap);
+			cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+					   PATH_MAX, nls_codepage, remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -3948,8 +3951,9 @@ QInfRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-					PATH_MAX, nls_codepage, remap);
+			cifsConvertToUTF16((__le16 *) pSMB->FileName,
+					   searchName, PATH_MAX, nls_codepage,
+					   remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {
@@ -4086,8 +4090,8 @@ QPathInfoRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -4255,8 +4259,8 @@ UnixQPathInfoRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-				  PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -4344,8 +4348,8 @@ findFirstRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-				 PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+				       PATH_MAX, nls_codepage, remap);
 		/* We can not add the asterik earlier in case
 		it got remapped to 0xF03A as if it were part of the
 		directory name instead of a wildcard */
@@ -4656,8 +4660,9 @@ GetInodeNumberRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-					 PATH_MAX, nls_codepage, remap);
+			cifsConvertToUTF16((__le16 *) pSMB->FileName,
+					   searchName, PATH_MAX, nls_codepage,
+					   remap);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -4794,9 +4799,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 				rc = -ENOMEM;
 				goto parse_DFS_referrals_exit;
 			}
-			cifsConvertToUCS((__le16 *) tmp, searchName,
-					PATH_MAX, nls_codepage, remap);
-			node->path_consumed = cifs_ucs2_bytes(tmp,
+			cifsConvertToUTF16((__le16 *) tmp, searchName,
+					   PATH_MAX, nls_codepage, remap);
+			node->path_consumed = cifs_utf16_bytes(tmp,
 					le16_to_cpu(pSMBr->PathConsumed),
 					nls_codepage);
 			kfree(tmp);
@@ -4809,8 +4814,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 		/* copy DfsPath */
 		temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
 		max_len = data_end - temp;
-		node->path_name = cifs_strndup_from_ucs(temp, max_len,
-						      is_unicode, nls_codepage);
+		node->path_name = cifs_strndup_from_utf16(temp, max_len,
+						is_unicode, nls_codepage);
 		if (!node->path_name) {
 			rc = -ENOMEM;
 			goto parse_DFS_referrals_exit;
@@ -4819,8 +4824,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
 		/* copy link target UNC */
 		temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
 		max_len = data_end - temp;
-		node->node_name = cifs_strndup_from_ucs(temp, max_len,
-						      is_unicode, nls_codepage);
+		node->node_name = cifs_strndup_from_utf16(temp, max_len,
+						is_unicode, nls_codepage);
 		if (!node->node_name)
 			rc = -ENOMEM;
 	}
@@ -4873,8 +4878,9 @@ getDFSRetry:
 	if (ses->capabilities & CAP_UNICODE) {
 		pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
-				     searchName, PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->RequestFileName,
+				       searchName, PATH_MAX, nls_codepage,
+				       remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -5506,8 +5512,8 @@ SetEOFRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -5796,8 +5802,8 @@ SetTimesRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -5877,8 +5883,8 @@ SetAttrLgcyRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-			ConvertToUCS((__le16 *) pSMB->fileName, fileName,
-				PATH_MAX, nls_codepage);
+			ConvertToUTF16((__le16 *) pSMB->fileName, fileName,
+				       PATH_MAX, nls_codepage);
 		name_len++;     /* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -6030,8 +6036,8 @@ setPermsRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -6123,8 +6129,8 @@ QAllEAsRetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		list_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName,
+				       PATH_MAX, nls_codepage, remap);
 		list_len++;	/* trailing null */
 		list_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
@@ -6301,8 +6307,8 @@ SetEARetry:
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len =
-		    cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
-				     PATH_MAX, nls_codepage, remap);
+		    cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName,
+				       PATH_MAX, nls_codepage, remap);
 		name_len++;	/* trailing null */
 		name_len *= 2;
 	} else {	/* BB improve the check for buffer overruns BB */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4666780..986709a 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -38,6 +38,7 @@
 #include <asm/processor.h>
 #include <linux/inet.h>
 #include <linux/module.h>
+#include <keys/user-type.h>
 #include <net/ipv6.h>
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -225,74 +226,90 @@ static int check2ndT2(struct smb_hdr *pSMB)
 
 static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
 {
-	struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
+	struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond;
 	struct smb_t2_rsp *pSMBt  = (struct smb_t2_rsp *)pTargetSMB;
-	char *data_area_of_target;
-	char *data_area_of_buf2;
+	char *data_area_of_tgt;
+	char *data_area_of_src;
 	int remaining;
-	unsigned int byte_count, total_in_buf;
-	__u16 total_data_size, total_in_buf2;
+	unsigned int byte_count, total_in_tgt;
+	__u16 tgt_total_cnt, src_total_cnt, total_in_src;
 
-	total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
+	src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount);
+	tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
 
-	if (total_data_size !=
-	    get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount))
-		cFYI(1, "total data size of primary and secondary t2 differ");
+	if (tgt_total_cnt != src_total_cnt)
+		cFYI(1, "total data count of primary and secondary t2 differ "
+			"source=%hu target=%hu", src_total_cnt, tgt_total_cnt);
 
-	total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
+	total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
 
-	remaining = total_data_size - total_in_buf;
+	remaining = tgt_total_cnt - total_in_tgt;
 
-	if (remaining < 0)
+	if (remaining < 0) {
+		cFYI(1, "Server sent too much data. tgt_total_cnt=%hu "
+			"total_in_tgt=%hu", tgt_total_cnt, total_in_tgt);
 		return -EPROTO;
+	}
 
-	if (remaining == 0) /* nothing to do, ignore */
+	if (remaining == 0) {
+		/* nothing to do, ignore */
+		cFYI(1, "no more data remains");
 		return 0;
+	}
 
-	total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount);
-	if (remaining < total_in_buf2) {
+	total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount);
+	if (remaining < total_in_src)
 		cFYI(1, "transact2 2nd response contains too much data");
-	}
 
 	/* find end of first SMB data area */
-	data_area_of_target = (char *)&pSMBt->hdr.Protocol +
+	data_area_of_tgt = (char *)&pSMBt->hdr.Protocol +
 				get_unaligned_le16(&pSMBt->t2_rsp.DataOffset);
-	/* validate target area */
 
-	data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol +
-				get_unaligned_le16(&pSMB2->t2_rsp.DataOffset);
+	/* validate target area */
+	data_area_of_src = (char *)&pSMBs->hdr.Protocol +
+				get_unaligned_le16(&pSMBs->t2_rsp.DataOffset);
 
-	data_area_of_target += total_in_buf;
+	data_area_of_tgt += total_in_tgt;
 
-	/* copy second buffer into end of first buffer */
-	total_in_buf += total_in_buf2;
+	total_in_tgt += total_in_src;
 	/* is the result too big for the field? */
-	if (total_in_buf > USHRT_MAX)
+	if (total_in_tgt > USHRT_MAX) {
+		cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt);
 		return -EPROTO;
-	put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount);
+	}
+	put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount);
 
 	/* fix up the BCC */
 	byte_count = get_bcc(pTargetSMB);
-	byte_count += total_in_buf2;
+	byte_count += total_in_src;
 	/* is the result too big for the field? */
-	if (byte_count > USHRT_MAX)
+	if (byte_count > USHRT_MAX) {
+		cFYI(1, "coalesced BCC too large (%u)", byte_count);
 		return -EPROTO;
+	}
 	put_bcc(byte_count, pTargetSMB);
 
 	byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
-	byte_count += total_in_buf2;
+	byte_count += total_in_src;
 	/* don't allow buffer to overflow */
-	if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
+	if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
+		cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count);
 		return -ENOBUFS;
+	}
 	pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
 
-	memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
+	/* copy second buffer into end of first buffer */
+	memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
 
-	if (remaining == total_in_buf2) {
-		cFYI(1, "found the last secondary response");
-		return 0; /* we are done */
-	} else /* more responses to go */
+	if (remaining != total_in_src) {
+		/* more responses to go */
+		cFYI(1, "waiting for more secondary responses");
 		return 1;
+	}
+
+	/* we are done */
+	cFYI(1, "found the last secondary response");
+	return 0;
 }
 
 static void
@@ -1578,11 +1595,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
 		}
 	}
 
-	if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) {
-		cERROR(1, "Multiuser mounts currently require krb5 "
-			  "authentication!");
+#ifndef CONFIG_KEYS
+	/* Muliuser mounts require CONFIG_KEYS support */
+	if (vol->multiuser) {
+		cERROR(1, "Multiuser mounts require kernels with "
+			  "CONFIG_KEYS enabled.");
 		goto cifs_parse_mount_err;
 	}
+#endif
 
 	if (vol->UNCip == NULL)
 		vol->UNCip = &vol->UNC[2];
@@ -1981,10 +2001,16 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol)
 			return 0;
 		break;
 	default:
+		/* NULL username means anonymous session */
+		if (ses->user_name == NULL) {
+			if (!vol->nullauth)
+				return 0;
+			break;
+		}
+
 		/* anything else takes username/password */
-		if (ses->user_name == NULL)
-			return 0;
-		if (strncmp(ses->user_name, vol->username,
+		if (strncmp(ses->user_name,
+			    vol->username ? vol->username : "",
 			    MAX_USERNAME_SIZE))
 			return 0;
 		if (strlen(vol->username) != 0 &&
@@ -2039,6 +2065,132 @@ cifs_put_smb_ses(struct cifs_ses *ses)
 	cifs_put_tcp_session(server);
 }
 
+#ifdef CONFIG_KEYS
+
+/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */
+#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1)
+
+/* Populate username and pw fields from keyring if possible */
+static int
+cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
+{
+	int rc = 0;
+	char *desc, *delim, *payload;
+	ssize_t len;
+	struct key *key;
+	struct TCP_Server_Info *server = ses->server;
+	struct sockaddr_in *sa;
+	struct sockaddr_in6 *sa6;
+	struct user_key_payload *upayload;
+
+	desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	/* try to find an address key first */
+	switch (server->dstaddr.ss_family) {
+	case AF_INET:
+		sa = (struct sockaddr_in *)&server->dstaddr;
+		sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr);
+		break;
+	case AF_INET6:
+		sa6 = (struct sockaddr_in6 *)&server->dstaddr;
+		sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr);
+		break;
+	default:
+		cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family);
+		rc = -EINVAL;
+		goto out_err;
+	}
+
+	cFYI(1, "%s: desc=%s", __func__, desc);
+	key = request_key(&key_type_logon, desc, "");
+	if (IS_ERR(key)) {
+		if (!ses->domainName) {
+			cFYI(1, "domainName is NULL");
+			rc = PTR_ERR(key);
+			goto out_err;
+		}
+
+		/* didn't work, try to find a domain key */
+		sprintf(desc, "cifs:d:%s", ses->domainName);
+		cFYI(1, "%s: desc=%s", __func__, desc);
+		key = request_key(&key_type_logon, desc, "");
+		if (IS_ERR(key)) {
+			rc = PTR_ERR(key);
+			goto out_err;
+		}
+	}
+
+	down_read(&key->sem);
+	upayload = key->payload.data;
+	if (IS_ERR_OR_NULL(upayload)) {
+		rc = PTR_ERR(key);
+		goto out_key_put;
+	}
+
+	/* find first : in payload */
+	payload = (char *)upayload->data;
+	delim = strnchr(payload, upayload->datalen, ':');
+	cFYI(1, "payload=%s", payload);
+	if (!delim) {
+		cFYI(1, "Unable to find ':' in payload (datalen=%d)",
+				upayload->datalen);
+		rc = -EINVAL;
+		goto out_key_put;
+	}
+
+	len = delim - payload;
+	if (len > MAX_USERNAME_SIZE || len <= 0) {
+		cFYI(1, "Bad value from username search (len=%ld)", len);
+		rc = -EINVAL;
+		goto out_key_put;
+	}
+
+	vol->username = kstrndup(payload, len, GFP_KERNEL);
+	if (!vol->username) {
+		cFYI(1, "Unable to allocate %ld bytes for username", len);
+		rc = -ENOMEM;
+		goto out_key_put;
+	}
+	cFYI(1, "%s: username=%s", __func__, vol->username);
+
+	len = key->datalen - (len + 1);
+	if (len > MAX_PASSWORD_SIZE || len <= 0) {
+		cFYI(1, "Bad len for password search (len=%ld)", len);
+		rc = -EINVAL;
+		kfree(vol->username);
+		vol->username = NULL;
+		goto out_key_put;
+	}
+
+	++delim;
+	vol->password = kstrndup(delim, len, GFP_KERNEL);
+	if (!vol->password) {
+		cFYI(1, "Unable to allocate %ld bytes for password", len);
+		rc = -ENOMEM;
+		kfree(vol->username);
+		vol->username = NULL;
+		goto out_key_put;
+	}
+
+out_key_put:
+	up_read(&key->sem);
+	key_put(key);
+out_err:
+	kfree(desc);
+	cFYI(1, "%s: returning %d", __func__, rc);
+	return rc;
+}
+#else /* ! CONFIG_KEYS */
+static inline int
+cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)),
+		   struct cifs_ses *ses __attribute__((unused)))
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_KEYS */
+
 static bool warned_on_ntlm;  /* globals init to false automatically */
 
 static struct cifs_ses *
@@ -2914,18 +3066,33 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 #define CIFS_DEFAULT_IOSIZE (1024 * 1024)
 
 /*
- * Windows only supports a max of 60k reads. Default to that when posix
- * extensions aren't in force.
+ * Windows only supports a max of 60kb reads and 65535 byte writes. Default to
+ * those values when posix extensions aren't in force. In actuality here, we
+ * use 65536 to allow for a write that is a multiple of 4k. Most servers seem
+ * to be ok with the extra byte even though Windows doesn't send writes that
+ * are that large.
+ *
+ * Citation:
+ *
+ * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx
  */
 #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024)
+#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536)
 
 static unsigned int
 cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 {
 	__u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
 	struct TCP_Server_Info *server = tcon->ses->server;
-	unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
-				CIFS_DEFAULT_IOSIZE;
+	unsigned int wsize;
+
+	/* start with specified wsize, or default */
+	if (pvolume_info->wsize)
+		wsize = pvolume_info->wsize;
+	else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
+		wsize = CIFS_DEFAULT_IOSIZE;
+	else
+		wsize = CIFS_DEFAULT_NON_POSIX_WSIZE;
 
 	/* can server support 24-bit write sizes? (via UNIX extensions) */
 	if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
@@ -3136,10 +3303,9 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
 		return -EINVAL;
 
 	if (volume_info->nullauth) {
-		cFYI(1, "null user");
-		volume_info->username = kzalloc(1, GFP_KERNEL);
-		if (volume_info->username == NULL)
-			return -ENOMEM;
+		cFYI(1, "Anonymous login");
+		kfree(volume_info->username);
+		volume_info->username = NULL;
 	} else if (volume_info->username) {
 		/* BB fixme parse for domain name here */
 		cFYI(1, "Username: %s", volume_info->username);
@@ -3478,7 +3644,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
 		length =
-		    cifs_strtoUCS((__le16 *) bcc_ptr, tree,
+		    cifs_strtoUTF16((__le16 *) bcc_ptr, tree,
 			6 /* max utf8 char length in bytes */ *
 			(/* server len*/ + 256 /* share len */), nls_codepage);
 		bcc_ptr += 2 * length;	/* convert num 16 bit words to bytes */
@@ -3533,7 +3699,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
 
 		/* mostly informational -- no need to fail on error here */
 		kfree(tcon->nativeFileSystem);
-		tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
+		tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr,
 						      bytes_left, is_unicode,
 						      nls_codepage);
 
@@ -3657,16 +3823,38 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses,
 	return rc;
 }
 
+static int
+cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses)
+{
+	switch (ses->server->secType) {
+	case Kerberos:
+		vol->secFlg = CIFSSEC_MUST_KRB5;
+		return 0;
+	case NTLMv2:
+		vol->secFlg = CIFSSEC_MUST_NTLMV2;
+		break;
+	case NTLM:
+		vol->secFlg = CIFSSEC_MUST_NTLM;
+		break;
+	case RawNTLMSSP:
+		vol->secFlg = CIFSSEC_MUST_NTLMSSP;
+		break;
+	case LANMAN:
+		vol->secFlg = CIFSSEC_MUST_LANMAN;
+		break;
+	}
+
+	return cifs_set_cifscreds(vol, ses);
+}
+
 static struct cifs_tcon *
 cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
 {
+	int rc;
 	struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
 	struct cifs_ses *ses;
 	struct cifs_tcon *tcon = NULL;
 	struct smb_vol *vol_info;
-	char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */
-			   /* We used to have this as MAX_USERNAME which is   */
-			   /* way too big now (256 instead of 32) */
 
 	vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL);
 	if (vol_info == NULL) {
@@ -3674,8 +3862,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
 		goto out;
 	}
 
-	snprintf(username, sizeof(username), "krb50x%x", fsuid);
-	vol_info->username = username;
 	vol_info->local_nls = cifs_sb->local_nls;
 	vol_info->linux_uid = fsuid;
 	vol_info->cred_uid = fsuid;
@@ -3685,8 +3871,11 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
 	vol_info->local_lease = master_tcon->local_lease;
 	vol_info->no_linux_ext = !master_tcon->unix_ext;
 
-	/* FIXME: allow for other secFlg settings */
-	vol_info->secFlg = CIFSSEC_MUST_KRB5;
+	rc = cifs_set_vol_auth(vol_info, master_tcon->ses);
+	if (rc) {
+		tcon = ERR_PTR(rc);
+		goto out;
+	}
 
 	/* get a reference for the same TCP session */
 	spin_lock(&cifs_tcp_ses_lock);
@@ -3709,6 +3898,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid)
 	if (ses->capabilities & CAP_UNIX)
 		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
 out:
+	kfree(vol_info->username);
+	kfree(vol_info->password);
 	kfree(vol_info);
 
 	return tcon;
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index a090bbe..e2bbc68 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -647,10 +647,11 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
 
 		name.name = scratch_buf;
 		name.len =
-			cifs_from_ucs2((char *)name.name, (__le16 *)de.name,
-				       UNICODE_NAME_MAX,
-				       min(de.namelen, (size_t)max_len), nlt,
-				       cifs_sb->mnt_cifs_flags &
+			cifs_from_utf16((char *)name.name, (__le16 *)de.name,
+					UNICODE_NAME_MAX,
+					min_t(size_t, de.namelen,
+					      (size_t)max_len), nlt,
+					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 		name.len -= nls_nullsize(nlt);
 	} else {
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 4ec3ee9..d85efad 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -167,16 +167,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp)
 	int bytes_ret = 0;
 
 	/* Copy OS version */
-	bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
-				  nls_cp);
+	bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32,
+				    nls_cp);
 	bcc_ptr += 2 * bytes_ret;
-	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release,
-				  32, nls_cp);
+	bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release,
+				    32, nls_cp);
 	bcc_ptr += 2 * bytes_ret;
 	bcc_ptr += 2; /* trailing null */
 
-	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
-				  32, nls_cp);
+	bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+				    32, nls_cp);
 	bcc_ptr += 2 * bytes_ret;
 	bcc_ptr += 2; /* trailing null */
 
@@ -197,8 +197,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses,
 		*(bcc_ptr+1) = 0;
 		bytes_ret = 0;
 	} else
-		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName,
-					  256, nls_cp);
+		bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName,
+					    256, nls_cp);
 	bcc_ptr += 2 * bytes_ret;
 	bcc_ptr += 2;  /* account for null terminator */
 
@@ -226,8 +226,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
 		*bcc_ptr = 0;
 		*(bcc_ptr+1) = 0;
 	} else {
-		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
-					  MAX_USERNAME_SIZE, nls_cp);
+		bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name,
+					    MAX_USERNAME_SIZE, nls_cp);
 	}
 	bcc_ptr += 2 * bytes_ret;
 	bcc_ptr += 2; /* account for null termination */
@@ -287,7 +287,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 	cFYI(1, "bleft %d", bleft);
 
 	kfree(ses->serverOS);
-	ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+	ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
 	cFYI(1, "serverOS=%s", ses->serverOS);
 	len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
 	data += len;
@@ -296,7 +296,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 		return;
 
 	kfree(ses->serverNOS);
-	ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+	ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
 	cFYI(1, "serverNOS=%s", ses->serverNOS);
 	len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
 	data += len;
@@ -305,7 +305,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses,
 		return;
 
 	kfree(ses->serverDomain);
-	ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+	ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp);
 	cFYI(1, "serverDomain=%s", ses->serverDomain);
 
 	return;
@@ -502,8 +502,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
 		tmp += 2;
 	} else {
 		int len;
-		len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
-				    MAX_USERNAME_SIZE, nls_cp);
+		len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
+				      MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
 		sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->DomainName.Length = cpu_to_le16(len);
@@ -518,8 +518,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
 		tmp += 2;
 	} else {
 		int len;
-		len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
-				    MAX_USERNAME_SIZE, nls_cp);
+		len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
+				      MAX_USERNAME_SIZE, nls_cp);
 		len *= 2; /* unicode is 2 bytes each */
 		sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
 		sec_blob->UserName.Length = cpu_to_le16(len);
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 80d8508..d5cd9aa 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -213,7 +213,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16,
 
 	/* Password cannot be longer than 128 characters */
 	if (passwd) /* Password must be converted to NT unicode */
-		len = cifs_strtoUCS(wpwd, passwd, 128, codepage);
+		len = cifs_strtoUTF16(wpwd, passwd, 128, codepage);
 	else {
 		len = 0;
 		*wpwd = 0; /* Ensure string is null terminated */
diff --git a/fs/dcache.c b/fs/dcache.c
index 16a53cc..536b969 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2466,7 +2466,7 @@ static int prepend_path(const struct path *path,
 	bool slash = false;
 	int error = 0;
 
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	while (dentry != root->dentry || vfsmnt != root->mnt) {
 		struct dentry * parent;
 
@@ -2497,7 +2497,7 @@ static int prepend_path(const struct path *path,
 		error = prepend(buffer, buflen, "/", 1);
 
 out:
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 	return error;
 
 global_root:
@@ -2968,7 +2968,7 @@ __setup("dhash_entries=", set_dhash_entries);
 
 static void __init dcache_init_early(void)
 {
-	int loop;
+	unsigned int loop;
 
 	/* If hashes are distributed across NUMA nodes, defer
 	 * hash allocation until vmalloc space is available.
@@ -2986,13 +2986,13 @@ static void __init dcache_init_early(void)
 					&d_hash_mask,
 					0);
 
-	for (loop = 0; loop < (1 << d_hash_shift); loop++)
+	for (loop = 0; loop < (1U << d_hash_shift); loop++)
 		INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 static void __init dcache_init(void)
 {
-	int loop;
+	unsigned int loop;
 
 	/* 
 	 * A constructor could be added for stable state like the lists,
@@ -3016,7 +3016,7 @@ static void __init dcache_init(void)
 					&d_hash_mask,
 					0);
 
-	for (loop = 0; loop < (1 << d_hash_shift); loop++)
+	for (loop = 0; loop < (1U << d_hash_shift); loop++)
 		INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 2a83425..d3c8776 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -2026,6 +2026,17 @@ out:
 	return;
 }
 
+static size_t ecryptfs_max_decoded_size(size_t encoded_size)
+{
+	/* Not exact; conservatively long. Every block of 4
+	 * encoded characters decodes into a block of 3
+	 * decoded characters. This segment of code provides
+	 * the caller with the maximum amount of allocated
+	 * space that @dst will need to point to in a
+	 * subsequent call. */
+	return ((encoded_size + 1) * 3) / 4;
+}
+
 /**
  * ecryptfs_decode_from_filename
  * @dst: If NULL, this function only sets @dst_size and returns. If
@@ -2044,13 +2055,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size,
 	size_t dst_byte_offset = 0;
 
 	if (dst == NULL) {
-		/* Not exact; conservatively long. Every block of 4
-		 * encoded characters decodes into a block of 3
-		 * decoded characters. This segment of code provides
-		 * the caller with the maximum amount of allocated
-		 * space that @dst will need to point to in a
-		 * subsequent call. */
-		(*dst_size) = (((src_size + 1) * 3) / 4);
+		(*dst_size) = ecryptfs_max_decoded_size(src_size);
 		goto out;
 	}
 	while (src_byte_offset < src_size) {
@@ -2275,3 +2280,52 @@ out_free:
 out:
 	return rc;
 }
+
+#define ENC_NAME_MAX_BLOCKLEN_8_OR_16	143
+
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+			   struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
+{
+	struct blkcipher_desc desc;
+	struct mutex *tfm_mutex;
+	size_t cipher_blocksize;
+	int rc;
+
+	if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
+		(*namelen) = lower_namelen;
+		return 0;
+	}
+
+	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex,
+			mount_crypt_stat->global_default_fn_cipher_name);
+	if (unlikely(rc)) {
+		(*namelen) = 0;
+		return rc;
+	}
+
+	mutex_lock(tfm_mutex);
+	cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm);
+	mutex_unlock(tfm_mutex);
+
+	/* Return an exact amount for the common cases */
+	if (lower_namelen == NAME_MAX
+	    && (cipher_blocksize == 8 || cipher_blocksize == 16)) {
+		(*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16;
+		return 0;
+	}
+
+	/* Return a safe estimate for the uncommon cases */
+	(*namelen) = lower_namelen;
+	(*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE;
+	/* Since this is the max decoded size, subtract 1 "decoded block" len */
+	(*namelen) = ecryptfs_max_decoded_size(*namelen) - 3;
+	(*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE;
+	(*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES;
+	/* Worst case is that the filename is padded nearly a full block size */
+	(*namelen) -= cipher_blocksize - 1;
+
+	if ((*namelen) < 0)
+		(*namelen) = 0;
+
+	return 0;
+}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a9f29b1..7cad6b0 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -157,6 +157,9 @@ ecryptfs_get_key_payload_data(struct key *key)
 #define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */
 #define MD5_DIGEST_SIZE 16
 #define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE
+#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)
+#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (ECRYPTFS_TAG_70_MIN_METADATA_SIZE \
+					   + 1)
 #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED."
 #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23
 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED."
@@ -696,6 +699,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
 			     size_t *packet_size,
 			     struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
 			     char *data, size_t max_packet_size);
+int ecryptfs_set_f_namelen(long *namelen, long lower_namelen,
+			   struct ecryptfs_mount_crypt_stat *mount_crypt_stat);
 int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
 		       loff_t offset);
 
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index ac1ad48..06aab59 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -678,10 +678,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
 	 * Octets N3-N4: Block-aligned encrypted filename
 	 *  - Consists of a minimum number of random characters, a \0
 	 *    separator, and then the filename */
-	s->max_packet_size = (1                   /* Tag 70 identifier */
-			      + 3                 /* Max Tag 70 packet size */
-			      + ECRYPTFS_SIG_SIZE /* FNEK sig */
-			      + 1                 /* Cipher identifier */
+	s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE
 			      + s->block_aligned_filename_size);
 	if (dest == NULL) {
 		(*packet_size) = s->max_packet_size;
@@ -933,10 +930,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
 		goto out;
 	}
 	s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-	if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) {
+	if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
 		printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
 		       "at least [%d]\n", __func__, max_packet_size,
-			(1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1));
+		       ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
 		rc = -EINVAL;
 		goto out;
 	}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 6a44148..5e29bf4 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -146,7 +146,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
 			/* This is a header extent */
 			char *page_virt;
 
-			page_virt = kmap_atomic(page, KM_USER0);
+			page_virt = kmap_atomic(page);
 			memset(page_virt, 0, PAGE_CACHE_SIZE);
 			/* TODO: Support more than one header extent */
 			if (view_extent_num == 0) {
@@ -159,7 +159,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page,
 							       crypt_stat,
 							       &written);
 			}
-			kunmap_atomic(page_virt, KM_USER0);
+			kunmap_atomic(page_virt);
 			flush_dcache_page(page);
 			if (rc) {
 				printk(KERN_ERR "%s: Error reading xattr "
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 3745f7c..6d3c7f2 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -130,13 +130,13 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
 		pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
 		size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
 		size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
-		size_t total_remaining_bytes = ((offset + size) - pos);
+		loff_t total_remaining_bytes = ((offset + size) - pos);
 
 		if (num_bytes > total_remaining_bytes)
 			num_bytes = total_remaining_bytes;
 		if (pos < offset) {
 			/* remaining zeros to write, up to destination offset */
-			size_t total_remaining_zeros = (offset - pos);
+			loff_t total_remaining_zeros = (offset - pos);
 
 			if (num_bytes > total_remaining_zeros)
 				num_bytes = total_remaining_zeros;
@@ -151,7 +151,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
 			       ecryptfs_page_idx, rc);
 			goto out;
 		}
-		ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+		ecryptfs_page_virt = kmap_atomic(ecryptfs_page);
 
 		/*
 		 * pos: where we're now writing, offset: where the request was
@@ -174,7 +174,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
 			       (data + data_offset), num_bytes);
 			data_offset += num_bytes;
 		}
-		kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+		kunmap_atomic(ecryptfs_page_virt);
 		flush_dcache_page(ecryptfs_page);
 		SetPageUptodate(ecryptfs_page);
 		unlock_page(ecryptfs_page);
@@ -330,11 +330,11 @@ int ecryptfs_read(char *data, loff_t offset, size_t size,
 			       ecryptfs_page_idx, rc);
 			goto out;
 		}
-		ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+		ecryptfs_page_virt = kmap_atomic(ecryptfs_page);
 		memcpy((data + data_offset),
 		       ((char *)ecryptfs_page_virt + start_offset_in_page),
 		       num_bytes);
-		kunmap_atomic(ecryptfs_page_virt, KM_USER0);
+		kunmap_atomic(ecryptfs_page_virt);
 		flush_dcache_page(ecryptfs_page);
 		SetPageUptodate(ecryptfs_page);
 		unlock_page(ecryptfs_page);
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c
index 9df7fd6..cf15282 100644
--- a/fs/ecryptfs/super.c
+++ b/fs/ecryptfs/super.c
@@ -30,6 +30,8 @@
 #include <linux/seq_file.h>
 #include <linux/file.h>
 #include <linux/crypto.h>
+#include <linux/statfs.h>
+#include <linux/magic.h>
 #include "ecryptfs_kernel.h"
 
 struct kmem_cache *ecryptfs_inode_info_cache;
@@ -102,10 +104,20 @@ static void ecryptfs_destroy_inode(struct inode *inode)
 static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+	int rc;
 
 	if (!lower_dentry->d_sb->s_op->statfs)
 		return -ENOSYS;
-	return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+
+	rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf);
+	if (rc)
+		return rc;
+
+	buf->f_type = ECRYPTFS_SUPER_MAGIC;
+	rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen,
+	       &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat);
+
+	return rc;
 }
 
 /**
diff --git a/fs/exec.c b/fs/exec.c
index aeb135c..d0be7f3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1338,13 +1338,13 @@ int remove_arg_zero(struct linux_binprm *bprm)
 			ret = -EFAULT;
 			goto out;
 		}
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 
 		for (; offset < PAGE_SIZE && kaddr[offset];
 				offset++, bprm->p++)
 			;
 
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		put_arg_page(page);
 
 		if (offset == PAGE_SIZE)
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c
index 8040583..c61e62a 100644
--- a/fs/exofs/dir.c
+++ b/fs/exofs/dir.c
@@ -597,7 +597,7 @@ int exofs_make_empty(struct inode *inode, struct inode *parent)
 		goto fail;
 	}
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	de = (struct exofs_dir_entry *)kaddr;
 	de->name_len = 1;
 	de->rec_len = cpu_to_le16(EXOFS_DIR_REC_LEN(1));
@@ -611,7 +611,7 @@ int exofs_make_empty(struct inode *inode, struct inode *parent)
 	de->inode_no = cpu_to_le64(parent->i_ino);
 	memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR));
 	exofs_set_de_type(de, inode);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	err = exofs_commit_chunk(page, 0, chunk_size);
 fail:
 	page_cache_release(page);
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index d37df35..0f4f5c9 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -645,7 +645,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
 		unlock_page(page);
 		goto fail;
 	}
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memset(kaddr, 0, chunk_size);
 	de = (struct ext2_dir_entry_2 *)kaddr;
 	de->name_len = 1;
@@ -660,7 +660,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
 	de->inode = cpu_to_le32(parent->i_ino);
 	memcpy (de->name, "..\0", 4);
 	ext2_set_de_type (de, inode);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	err = ext2_commit_chunk(page, 0, chunk_size);
 fail:
 	page_cache_release(page);
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 1089f76..2de655f 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -77,10 +77,11 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		flags = flags & EXT2_FL_USER_MODIFIABLE;
 		flags |= oldflags & ~EXT2_FL_USER_MODIFIABLE;
 		ei->i_flags = flags;
-		mutex_unlock(&inode->i_mutex);
 
 		ext2_set_inode_flags(inode);
 		inode->i_ctime = CURRENT_TIME_SEC;
+		mutex_unlock(&inode->i_mutex);
+
 		mark_inode_dirty(inode);
 setflags_out:
 		mnt_drop_write_file(filp);
@@ -88,20 +89,29 @@ setflags_out:
 	}
 	case EXT2_IOC_GETVERSION:
 		return put_user(inode->i_generation, (int __user *) arg);
-	case EXT2_IOC_SETVERSION:
+	case EXT2_IOC_SETVERSION: {
+		__u32 generation;
+
 		if (!inode_owner_or_capable(inode))
 			return -EPERM;
 		ret = mnt_want_write_file(filp);
 		if (ret)
 			return ret;
-		if (get_user(inode->i_generation, (int __user *) arg)) {
+		if (get_user(generation, (int __user *) arg)) {
 			ret = -EFAULT;
-		} else {
-			inode->i_ctime = CURRENT_TIME_SEC;
-			mark_inode_dirty(inode);
+			goto setversion_out;
 		}
+
+		mutex_lock(&inode->i_mutex);
+		inode->i_ctime = CURRENT_TIME_SEC;
+		inode->i_generation = generation;
+		mutex_unlock(&inode->i_mutex);
+
+		mark_inode_dirty(inode);
+setversion_out:
 		mnt_drop_write_file(filp);
 		return ret;
+	}
 	case EXT2_IOC_GETRSVSZ:
 		if (test_opt(inode->i_sb, RESERVATION)
 			&& S_ISREG(inode->i_mode)
diff --git a/fs/file_table.c b/fs/file_table.c
index 20002e3..50de47d 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -34,7 +34,6 @@ struct files_stat_struct files_stat = {
 	.max_files = NR_FILE
 };
 
-DECLARE_LGLOCK(files_lglock);
 DEFINE_LGLOCK(files_lglock);
 
 /* SLAB cache for file structures */
@@ -422,9 +421,9 @@ static inline void __file_sb_list_add(struct file *file, struct super_block *sb)
  */
 void file_sb_list_add(struct file *file, struct super_block *sb)
 {
-	lg_local_lock(files_lglock);
+	lg_local_lock(&files_lglock);
 	__file_sb_list_add(file, sb);
-	lg_local_unlock(files_lglock);
+	lg_local_unlock(&files_lglock);
 }
 
 /**
@@ -437,9 +436,9 @@ void file_sb_list_add(struct file *file, struct super_block *sb)
 void file_sb_list_del(struct file *file)
 {
 	if (!list_empty(&file->f_u.fu_list)) {
-		lg_local_lock_cpu(files_lglock, file_list_cpu(file));
+		lg_local_lock_cpu(&files_lglock, file_list_cpu(file));
 		list_del_init(&file->f_u.fu_list);
-		lg_local_unlock_cpu(files_lglock, file_list_cpu(file));
+		lg_local_unlock_cpu(&files_lglock, file_list_cpu(file));
 	}
 }
 
@@ -486,7 +485,7 @@ void mark_files_ro(struct super_block *sb)
 	struct file *f;
 
 retry:
-	lg_global_lock(files_lglock);
+	lg_global_lock(&files_lglock);
 	do_file_list_for_each_entry(sb, f) {
 		struct vfsmount *mnt;
 		if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
@@ -503,12 +502,12 @@ retry:
 		file_release_write(f);
 		mnt = mntget(f->f_path.mnt);
 		/* This can sleep, so we can't hold the spinlock. */
-		lg_global_unlock(files_lglock);
+		lg_global_unlock(&files_lglock);
 		mnt_drop_write(mnt);
 		mntput(mnt);
 		goto retry;
 	} while_file_list_for_each_entry;
-	lg_global_unlock(files_lglock);
+	lg_global_unlock(&files_lglock);
 }
 
 void __init files_init(unsigned long mempages)
@@ -526,6 +525,6 @@ void __init files_init(unsigned long mempages)
 	n = (mempages * (PAGE_SIZE / 1024)) / 10;
 	files_stat.max_files = max_t(unsigned long, n, NR_FILE);
 	files_defer_init();
-	lg_lock_init(files_lglock);
+	lg_lock_init(&files_lglock, "files_lglock");
 	percpu_counter_init(&nr_files, 0);
 } 
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 3426521..fc75f01 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -48,6 +48,8 @@
 #include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/module.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
 
 #include "fuse_i.h"
 
@@ -174,6 +176,419 @@ static long cuse_file_compat_ioctl(struct file *file, unsigned int cmd,
 	return fuse_do_ioctl(file, cmd, arg, flags);
 }
 
+struct fuse_dmmap_region {
+	u64 mapid;
+	u64 size;
+	pgoff_t nr_pages;
+	struct page **pages;
+	struct list_head list;
+	atomic_t ref;
+};
+
+/*
+ * fuse_dmmap_vm represents the result of a single mmap() call, which
+ * can be shared by multiple client vmas created by forking.
+ */
+struct fuse_dmmap_vm {
+	atomic_t open_count;
+	struct fuse_dmmap_region *region;
+};
+
+static void fuse_dmmap_region_put(struct fuse_conn *fc,
+				  struct fuse_dmmap_region *fdr)
+{
+	if (atomic_dec_and_lock(&fdr->ref, &fc->lock)) {
+		pgoff_t idx;
+
+		list_del(&fdr->list);
+		spin_unlock(&fc->lock);
+
+		for (idx = 0; idx < fdr->nr_pages; idx++)
+			if (fdr->pages[idx])
+				put_page(fdr->pages[idx]);
+
+		kfree(fdr->pages);
+		kfree(fdr);
+	}
+}
+
+static void fuse_dmmap_vm_open(struct vm_area_struct *vma)
+{
+	struct fuse_dmmap_vm *fdvm = vma->vm_private_data;
+
+	/* vma copied */
+	atomic_inc(&fdvm->open_count);
+}
+
+static void fuse_dmmap_vm_close(struct vm_area_struct *vma)
+{
+	struct fuse_dmmap_vm *fdvm = vma->vm_private_data;
+	struct fuse_file *ff = vma->vm_file->private_data;
+	struct fuse_conn *fc = ff->fc;
+	struct fuse_req *req;
+	struct fuse_munmap_in *inarg;
+
+	if (!atomic_dec_and_test(&fdvm->open_count))
+		return;
+	/*
+	 * Notify server that the mmap region has been unmapped.
+	 * Failing this might lead to resource leak in server, don't
+	 * fail.
+	 */
+	req = fuse_get_req_nofail(fc, vma->vm_file);
+	inarg = &req->misc.munmap_in;
+
+	inarg->fh = ff->fh;
+	inarg->mapid = fdvm->region->mapid;
+	inarg->size = fdvm->region->size;
+
+	req->in.h.opcode = FUSE_MUNMAP;
+	req->in.h.nodeid = ff->nodeid;
+	req->in.numargs = 1;
+	req->in.args[0].size = sizeof(*inarg);
+	req->in.args[0].value = inarg;
+
+	fuse_request_send(fc, req);
+	fuse_dmmap_region_put(fc, fdvm->region);
+	kfree(fdvm);
+}
+
+static struct page *fuse_dmmap_find_or_create_page(struct fuse_conn *fc,
+					   struct fuse_dmmap_region *fdr,
+					   pgoff_t index)
+{
+	struct page *new_page = NULL;
+	struct page *page;
+
+	BUG_ON(index >= fdr->nr_pages);
+
+	spin_lock(&fc->lock);
+	page = fdr->pages[index];
+	if (!page) {
+		spin_unlock(&fc->lock);
+		/* need to allocate and install a new page */
+		new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO);
+		if (!new_page)
+			return NULL;
+
+		/* try to install, check whether someone else already did it */
+		spin_lock(&fc->lock);
+		page = fdr->pages[index];
+		if (!page) {
+			page = fdr->pages[index] = new_page;
+			new_page = NULL;
+		}
+	}
+	get_page(page);
+	spin_unlock(&fc->lock);
+
+	if (new_page)
+		put_page(new_page);
+
+	return page;
+}
+
+static int fuse_dmmap_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct fuse_dmmap_vm *fdvm = vma->vm_private_data;
+	struct fuse_dmmap_region *fdr = fdvm->region;
+	struct fuse_file *ff = vma->vm_file->private_data;
+	struct fuse_conn *fc = ff->fc;
+
+	if (vmf->pgoff >= fdr->nr_pages)
+		return VM_FAULT_SIGBUS;
+
+	vmf->page = fuse_dmmap_find_or_create_page(fc, fdr, vmf->pgoff);
+	if (!vmf->page)
+		return VM_FAULT_OOM;
+
+	return 0;
+}
+
+static const struct vm_operations_struct fuse_dmmap_vm_ops = {
+	.open		= fuse_dmmap_vm_open,
+	.close		= fuse_dmmap_vm_close,
+	.fault		= fuse_dmmap_vm_fault,
+};
+
+static struct fuse_dmmap_region *fuse_dmmap_find_locked(struct fuse_conn *fc,
+							u64 mapid)
+{
+	struct fuse_dmmap_region *curr;
+	struct fuse_dmmap_region *fdr = NULL;
+
+	list_for_each_entry(curr, &fc->dmmap_list, list) {
+		if (curr->mapid == mapid) {
+			fdr = curr;
+			atomic_inc(&fdr->ref);
+			break;
+		}
+	}
+
+	return fdr;
+}
+
+static struct fuse_dmmap_region *fuse_dmmap_find(struct fuse_conn *fc,
+						 u64 mapid)
+{
+	struct fuse_dmmap_region *fdr;
+
+	spin_lock(&fc->lock);
+	fdr = fuse_dmmap_find_locked(fc, mapid);
+	spin_unlock(&fc->lock);
+
+	return fdr;
+}
+
+static struct fuse_dmmap_region *fuse_dmmap_get(struct fuse_conn *fc,
+						u64 mapid, u64 size)
+{
+	struct fuse_dmmap_region *fdr;
+	pgoff_t nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	if ((loff_t) (nr_pages << PAGE_SHIFT) < size)
+		return ERR_PTR(-EIO);
+
+	fdr = fuse_dmmap_find(fc, mapid);
+	if (fdr) {
+		if (fdr->size != size) {
+			fuse_dmmap_region_put(fc, fdr);
+			return ERR_PTR(-EIO);
+		}
+	} else {
+		struct fuse_dmmap_region *tmp;
+
+		fdr = kzalloc(sizeof(struct fuse_dmmap_region), GFP_KERNEL);
+		if (!fdr)
+			return ERR_PTR(-ENOMEM);
+
+		atomic_set(&fdr->ref, 1);
+		fdr->mapid = mapid;
+		fdr->size = size;
+		fdr->nr_pages = nr_pages;
+
+		fdr->pages = kzalloc(sizeof(struct page *) * nr_pages,
+				     GFP_KERNEL);
+		if (!fdr->pages) {
+			kfree(fdr);
+			return ERR_PTR(-ENOMEM);
+		}
+
+		spin_lock(&fc->lock);
+		tmp = fuse_dmmap_find_locked(fc, mapid);
+		if (tmp) {
+			kfree(fdr->pages);
+			kfree(fdr);
+			fdr = tmp;
+		} else {
+			list_add(&fdr->list, &fc->dmmap_list);
+		}
+		spin_unlock(&fc->lock);
+	}
+
+	return fdr;
+}
+
+static int cuse_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct fuse_file *ff = file->private_data;
+	struct fuse_conn *fc = ff->fc;
+	struct fuse_dmmap_vm *fdvm;
+	struct fuse_dmmap_region *fdr;
+	struct fuse_req *req = NULL;
+	struct fuse_mmap_in inarg;
+	struct fuse_mmap_out outarg;
+	int err;
+
+	if (fc->no_dmmap)
+		return -ENOSYS;
+
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+
+	/* ask server whether this mmap is okay and what the offset should be */
+	memset(&inarg, 0, sizeof(inarg));
+	inarg.fh = ff->fh;
+	inarg.addr = vma->vm_start;
+	inarg.len = vma->vm_end - vma->vm_start;
+	inarg.prot = ((vma->vm_flags & VM_READ) ? PROT_READ : 0) |
+		     ((vma->vm_flags & VM_WRITE) ? PROT_WRITE : 0) |
+		     ((vma->vm_flags & VM_EXEC) ? PROT_EXEC : 0);
+	inarg.flags = ((vma->vm_flags & VM_GROWSDOWN) ? MAP_GROWSDOWN : 0) |
+		      ((vma->vm_flags & VM_DENYWRITE) ? MAP_DENYWRITE : 0) |
+		      ((vma->vm_flags & VM_EXECUTABLE) ? MAP_EXECUTABLE : 0) |
+		      ((vma->vm_flags & VM_LOCKED) ? MAP_LOCKED : 0);
+	inarg.offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
+
+	req->in.h.opcode = FUSE_MMAP;
+	req->in.h.nodeid = ff->nodeid;
+	req->in.numargs = 1;
+	req->in.args[0].size = sizeof(inarg);
+	req->in.args[0].value = &inarg;
+	req->out.numargs = 1;
+	req->out.args[0].size = sizeof(outarg);
+	req->out.args[0].value = &outarg;
+
+	fuse_request_send(fc, req);
+	err = req->out.h.error;
+	if (err) {
+		if (err == -ENOSYS)
+			fc->no_dmmap = 1;
+		goto free_req;
+	}
+
+	fdr = fuse_dmmap_get(fc, outarg.mapid, outarg.size);
+	err = PTR_ERR(fdr);
+	if (IS_ERR(fdr))
+		goto free_req;
+
+	err = -ENOMEM;
+	fdvm = kzalloc(sizeof(*fdvm), GFP_KERNEL);
+	if (!fdvm) {
+		fuse_dmmap_region_put(fc, fdr);
+		goto free_req;
+	}
+	atomic_set(&fdvm->open_count, 1);
+	fdvm->region = fdr;
+
+	vma->vm_ops = &fuse_dmmap_vm_ops;
+	vma->vm_private_data = fdvm;
+	vma->vm_flags |= VM_DONTEXPAND;		/* disallow expansion for now */
+	err = 0;
+
+free_req:
+	fuse_put_request(fc, req);
+	return err;
+}
+
+static int fuse_notify_store_to_dmmap(struct fuse_conn *fc,
+				      struct fuse_copy_state *cs,
+				      u64 nodeid, u32 size, u64 pos)
+{
+	struct fuse_dmmap_region *fdr;
+	pgoff_t index;
+	unsigned int off;
+	int err;
+
+	fdr = fuse_dmmap_find(fc, nodeid);
+	if (!fdr)
+		return -ENOENT;
+
+	index = pos >> PAGE_SHIFT;
+	off = pos & ~PAGE_MASK;
+	if (pos > fdr->size)
+		size = 0;
+	else if (size > fdr->size - pos)
+		size = fdr->size - pos;
+
+	while (size) {
+		struct page *page;
+		unsigned int this_num;
+
+		err = -ENOMEM;
+		page = fuse_dmmap_find_or_create_page(fc, fdr, index);
+		if (!page)
+			goto out_iput;
+
+		this_num = min_t(unsigned, size, PAGE_SIZE - off);
+		err = fuse_copy_page(cs, &page, off, this_num, 0);
+		put_page(page);
+
+		if (err)
+			goto out_iput;
+
+		size -= this_num;
+		off = 0;
+		index++;
+	}
+
+	err = 0;
+
+out_iput:
+	fuse_dmmap_region_put(fc, fdr);
+
+	return err;
+}
+
+static void fuse_retrieve_dmmap_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+	release_pages(req->pages, req->num_pages, 0);
+}
+
+static int fuse_notify_retrieve_from_dmmap(struct fuse_conn *fc,
+				struct fuse_notify_retrieve_out *outarg)
+{
+	struct fuse_dmmap_region *fdr;
+	struct fuse_req *req;
+	pgoff_t index;
+	unsigned int num;
+	unsigned int offset;
+	size_t total_len = 0;
+	int err;
+
+	fdr = fuse_dmmap_find(fc, outarg->nodeid);
+	if (!fdr)
+		return -ENOENT;
+
+	req = fuse_get_req(fc);
+	err = PTR_ERR(req);
+	if (IS_ERR(req))
+		goto out_put_region;
+
+	offset = outarg->offset & ~PAGE_MASK;
+
+	req->in.h.opcode = FUSE_NOTIFY_REPLY;
+	req->in.h.nodeid = outarg->nodeid;
+	req->in.numargs = 2;
+	req->in.argpages = 1;
+	req->page_offset = offset;
+	req->end = fuse_retrieve_dmmap_end;
+
+	index = outarg->offset >> PAGE_SHIFT;
+	num = outarg->size;
+	if (outarg->offset > fdr->size)
+		num = 0;
+	else if (outarg->offset + num > fdr->size)
+		num = fdr->size - outarg->offset;
+
+	while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) {
+		struct page *page;
+		unsigned int this_num;
+
+		BUG_ON(index >= fdr->nr_pages);
+		spin_lock(&fc->lock);
+		page = fdr->pages[index];
+		if (!page)
+			page = ZERO_PAGE(0);
+		get_page(page);
+		spin_unlock(&fc->lock);
+
+		this_num = min_t(unsigned, num, PAGE_SIZE - offset);
+		req->pages[req->num_pages] = page;
+		req->num_pages++;
+
+		num -= this_num;
+		total_len += this_num;
+		index++;
+	}
+	req->misc.retrieve_in.offset = outarg->offset;
+	req->misc.retrieve_in.size = total_len;
+	req->in.args[0].size = sizeof(req->misc.retrieve_in);
+	req->in.args[0].value = &req->misc.retrieve_in;
+	req->in.args[1].size = total_len;
+
+	err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique);
+	if (err)
+		fuse_retrieve_dmmap_end(fc, req);
+
+out_put_region:
+	fuse_dmmap_region_put(fc, fdr);
+
+	return err;
+}
+
+
 static const struct file_operations cuse_frontend_fops = {
 	.owner			= THIS_MODULE,
 	.read			= cuse_read,
@@ -183,7 +598,8 @@ static const struct file_operations cuse_frontend_fops = {
 	.unlocked_ioctl		= cuse_file_ioctl,
 	.compat_ioctl		= cuse_file_compat_ioctl,
 	.poll			= fuse_file_poll,
-	.llseek		= noop_llseek,
+	.llseek			= noop_llseek,
+	.mmap			= cuse_mmap,
 };
 
 
@@ -461,6 +877,12 @@ static void cuse_fc_release(struct fuse_conn *fc)
 	kfree(cc);
 }
 
+static const struct fuse_conn_operations cuse_ops = {
+	.release = cuse_fc_release,
+	.notify_store = fuse_notify_store_to_dmmap,
+	.notify_retrieve = fuse_notify_retrieve_from_dmmap,
+};
+
 /**
  * cuse_channel_open - open method for /dev/cuse
  * @inode: inode for /dev/cuse
@@ -489,7 +911,7 @@ static int cuse_channel_open(struct inode *inode, struct file *file)
 	fuse_conn_init(&cc->fc);
 
 	INIT_LIST_HEAD(&cc->list);
-	cc->fc.release = cuse_fc_release;
+	cc->fc.ops = &cuse_ops;
 
 	cc->fc.connected = 1;
 	cc->fc.blocked = 0;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5f3368a..f81a85b 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -201,6 +201,7 @@ struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
 	req->waiting = 1;
 	return req;
 }
+EXPORT_SYMBOL_GPL(fuse_get_req_nofail);
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
@@ -463,8 +464,8 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req)
 }
 EXPORT_SYMBOL_GPL(fuse_request_send_background);
 
-static int fuse_request_send_notify_reply(struct fuse_conn *fc,
-					  struct fuse_req *req, u64 unique)
+int fuse_request_send_notify_reply(struct fuse_conn *fc,
+				   struct fuse_req *req, u64 unique)
 {
 	int err = -ENODEV;
 
@@ -479,6 +480,7 @@ static int fuse_request_send_notify_reply(struct fuse_conn *fc,
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(fuse_request_send_notify_reply);
 
 /*
  * Called under fc->lock
@@ -813,8 +815,8 @@ static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page,
  * Copy a page in the request to/from the userspace buffer.  Must be
  * done atomically
  */
-static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
-			  unsigned offset, unsigned count, int zeroing)
+int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
+		   unsigned offset, unsigned count, int zeroing)
 {
 	int err;
 	struct page *page = *pagep;
@@ -838,10 +840,10 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
 			}
 		}
 		if (page) {
-			void *mapaddr = kmap_atomic(page, KM_USER0);
+			void *mapaddr = kmap_atomic(page);
 			void *buf = mapaddr + offset;
 			offset += fuse_copy_do(cs, &buf, &count);
-			kunmap_atomic(mapaddr, KM_USER0);
+			kunmap_atomic(mapaddr);
 		} else
 			offset += fuse_copy_do(cs, NULL, &count);
 	}
@@ -849,6 +851,7 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
 		flush_dcache_page(page);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(fuse_copy_page);
 
 /* Copy pages in the request to/from userspace buffer */
 static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
@@ -1445,15 +1448,7 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
 			     struct fuse_copy_state *cs)
 {
 	struct fuse_notify_store_out outarg;
-	struct inode *inode;
-	struct address_space *mapping;
-	u64 nodeid;
 	int err;
-	pgoff_t index;
-	unsigned int offset;
-	unsigned int num;
-	loff_t file_size;
-	loff_t end;
 
 	err = -EINVAL;
 	if (size < sizeof(outarg))
@@ -1467,137 +1462,18 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
 	if (size - sizeof(outarg) != outarg.size)
 		goto out_finish;
 
-	nodeid = outarg.nodeid;
-
-	down_read(&fc->killsb);
+	err = fc->ops->notify_store(fc, cs, outarg.nodeid, outarg.size,
+				       outarg.offset);
 
-	err = -ENOENT;
-	if (!fc->sb)
-		goto out_up_killsb;
-
-	inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
-	if (!inode)
-		goto out_up_killsb;
-
-	mapping = inode->i_mapping;
-	index = outarg.offset >> PAGE_CACHE_SHIFT;
-	offset = outarg.offset & ~PAGE_CACHE_MASK;
-	file_size = i_size_read(inode);
-	end = outarg.offset + outarg.size;
-	if (end > file_size) {
-		file_size = end;
-		fuse_write_update_size(inode, file_size);
-	}
-
-	num = outarg.size;
-	while (num) {
-		struct page *page;
-		unsigned int this_num;
-
-		err = -ENOMEM;
-		page = find_or_create_page(mapping, index,
-					   mapping_gfp_mask(mapping));
-		if (!page)
-			goto out_iput;
-
-		this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
-		err = fuse_copy_page(cs, &page, offset, this_num, 0);
-		if (!err && offset == 0 && (num != 0 || file_size == end))
-			SetPageUptodate(page);
-		unlock_page(page);
-		page_cache_release(page);
-
-		if (err)
-			goto out_iput;
-
-		num -= this_num;
-		offset = 0;
-		index++;
-	}
-
-	err = 0;
-
-out_iput:
-	iput(inode);
-out_up_killsb:
-	up_read(&fc->killsb);
 out_finish:
 	fuse_copy_finish(cs);
 	return err;
 }
 
-static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req)
-{
-	release_pages(req->pages, req->num_pages, 0);
-}
-
-static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
-			 struct fuse_notify_retrieve_out *outarg)
-{
-	int err;
-	struct address_space *mapping = inode->i_mapping;
-	struct fuse_req *req;
-	pgoff_t index;
-	loff_t file_size;
-	unsigned int num;
-	unsigned int offset;
-	size_t total_len = 0;
-
-	req = fuse_get_req(fc);
-	if (IS_ERR(req))
-		return PTR_ERR(req);
-
-	offset = outarg->offset & ~PAGE_CACHE_MASK;
-
-	req->in.h.opcode = FUSE_NOTIFY_REPLY;
-	req->in.h.nodeid = outarg->nodeid;
-	req->in.numargs = 2;
-	req->in.argpages = 1;
-	req->page_offset = offset;
-	req->end = fuse_retrieve_end;
-
-	index = outarg->offset >> PAGE_CACHE_SHIFT;
-	file_size = i_size_read(inode);
-	num = outarg->size;
-	if (outarg->offset > file_size)
-		num = 0;
-	else if (outarg->offset + num > file_size)
-		num = file_size - outarg->offset;
-
-	while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) {
-		struct page *page;
-		unsigned int this_num;
-
-		page = find_get_page(mapping, index);
-		if (!page)
-			break;
-
-		this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
-		req->pages[req->num_pages] = page;
-		req->num_pages++;
-
-		num -= this_num;
-		total_len += this_num;
-		index++;
-	}
-	req->misc.retrieve_in.offset = outarg->offset;
-	req->misc.retrieve_in.size = total_len;
-	req->in.args[0].size = sizeof(req->misc.retrieve_in);
-	req->in.args[0].value = &req->misc.retrieve_in;
-	req->in.args[1].size = total_len;
-
-	err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique);
-	if (err)
-		fuse_retrieve_end(fc, req);
-
-	return err;
-}
-
 static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
 				struct fuse_copy_state *cs)
 {
 	struct fuse_notify_retrieve_out outarg;
-	struct inode *inode;
 	int err;
 
 	err = -EINVAL;
@@ -1610,18 +1486,7 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
 
 	fuse_copy_finish(cs);
 
-	down_read(&fc->killsb);
-	err = -ENOENT;
-	if (fc->sb) {
-		u64 nodeid = outarg.nodeid;
-
-		inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
-		if (inode) {
-			err = fuse_retrieve(fc, inode, &outarg);
-			iput(inode);
-		}
-	}
-	up_read(&fc->killsb);
+	err = fc->ops->notify_retrieve(fc, &outarg);
 
 	return err;
 
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 4a199fd..a841868 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1887,11 +1887,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 		    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
 			goto out;
 
-		vaddr = kmap_atomic(pages[0], KM_USER0);
+		vaddr = kmap_atomic(pages[0]);
 		err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr,
 					    transferred, in_iovs + out_iovs,
 					    (flags & FUSE_IOCTL_COMPAT) != 0);
-		kunmap_atomic(vaddr, KM_USER0);
+		kunmap_atomic(vaddr);
 		if (err)
 			goto out;
 
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 572cefc..51b7cb1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -285,6 +285,7 @@ struct fuse_req {
 		} write;
 		struct fuse_notify_retrieve_in retrieve_in;
 		struct fuse_lk_in lk_in;
+		struct fuse_munmap_in munmap_in;
 	} misc;
 
 	/** page vector */
@@ -312,6 +313,21 @@ struct fuse_req {
 	struct file *stolen_file;
 };
 
+struct fuse_copy_state;
+
+struct fuse_conn_operations {
+	/** Called on final put */
+	void (*release)(struct fuse_conn *);
+
+	/** Called to store data into a mapping */
+	int (*notify_store)(struct fuse_conn *, struct fuse_copy_state *,
+			    u64 nodeid, u32 size, u64 pos);
+
+	/** Called to retrieve data from a mapping */
+	int (*notify_retrieve)(struct fuse_conn *,
+			       struct fuse_notify_retrieve_out *);
+};
+
 /**
  * A Fuse connection.
  *
@@ -469,6 +485,9 @@ struct fuse_conn {
 	/** Is poll not implemented by fs? */
 	unsigned no_poll:1;
 
+	/** Is direct mmap not implemente by fs? */
+	unsigned no_dmmap:1;
+
 	/** Do multi-page cached writes */
 	unsigned big_writes:1;
 
@@ -511,14 +530,17 @@ struct fuse_conn {
 	/** Version counter for attribute changes */
 	u64 attr_version;
 
-	/** Called on final put */
-	void (*release)(struct fuse_conn *);
-
 	/** Super block for this connection. */
 	struct super_block *sb;
 
 	/** Read/write semaphore to hold when accessing sb. */
 	struct rw_semaphore killsb;
+
+	/** List of direct mmaps (currently CUSE only) */
+	struct list_head dmmap_list;
+
+	/** Operations that fuse and cuse can implement differently */
+	const struct fuse_conn_operations *ops;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -778,4 +800,11 @@ int fuse_dev_release(struct inode *inode, struct file *file);
 
 void fuse_write_update_size(struct inode *inode, loff_t pos);
 
+int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
+		   unsigned offset, unsigned count, int zeroing);
+
+int fuse_request_send_notify_reply(struct fuse_conn *fc,
+				   struct fuse_req *req, u64 unique);
+
+
 #endif /* _FS_FUSE_I_H */
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 64cf8d0..cdad212 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -541,6 +541,7 @@ void fuse_conn_init(struct fuse_conn *fc)
 	fc->blocked = 1;
 	fc->attr_version = 1;
 	get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
+	INIT_LIST_HEAD(&fc->dmmap_list);
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -550,7 +551,7 @@ void fuse_conn_put(struct fuse_conn *fc)
 		if (fc->destroy_req)
 			fuse_request_free(fc->destroy_req);
 		mutex_destroy(&fc->inst_mutex);
-		fc->release(fc);
+		fc->ops->release(fc);
 	}
 }
 EXPORT_SYMBOL_GPL(fuse_conn_put);
@@ -914,6 +915,168 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
 	return 0;
 }
 
+static int fuse_notify_store_to_inode(struct fuse_conn *fc,
+				      struct fuse_copy_state *cs,
+				      u64 nodeid, u32 size, u64 pos)
+{
+	struct inode *inode;
+	struct address_space *mapping;
+	pgoff_t index;
+	unsigned int off;
+	loff_t file_size;
+	loff_t end;
+	int err;
+
+	down_read(&fc->killsb);
+
+	err = -ENOENT;
+	if (!fc->sb)
+		goto out_up_killsb;
+
+	inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
+	if (!inode)
+		goto out_up_killsb;
+
+	mapping = inode->i_mapping;
+	index = pos >> PAGE_CACHE_SHIFT;
+	off = pos & ~PAGE_CACHE_MASK;
+	file_size = i_size_read(inode);
+	end = pos + size;
+	if (end > file_size) {
+		file_size = end;
+		fuse_write_update_size(inode, file_size);
+	}
+
+	while (size) {
+		struct page *page;
+		unsigned int this_num;
+
+		err = -ENOMEM;
+		page = find_or_create_page(mapping, index,
+					   mapping_gfp_mask(mapping));
+		if (!page)
+			goto out_iput;
+
+		this_num = min_t(unsigned, size, PAGE_CACHE_SIZE - off);
+		err = fuse_copy_page(cs, &page, off, this_num, 0);
+		if (!err && off == 0 && (size != 0 || file_size == end))
+			SetPageUptodate(page);
+		unlock_page(page);
+		page_cache_release(page);
+
+		if (err)
+			goto out_iput;
+
+		size -= this_num;
+		off = 0;
+		index++;
+	}
+
+	err = 0;
+
+out_iput:
+	iput(inode);
+out_up_killsb:
+	up_read(&fc->killsb);
+
+	return err;
+}
+
+static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req)
+{
+	release_pages(req->pages, req->num_pages, 0);
+}
+
+static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
+			 struct fuse_notify_retrieve_out *outarg)
+{
+	int err;
+	struct address_space *mapping = inode->i_mapping;
+	struct fuse_req *req;
+	pgoff_t index;
+	loff_t file_size;
+	unsigned int num;
+	unsigned int offset;
+	size_t total_len = 0;
+
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+
+	offset = outarg->offset & ~PAGE_CACHE_MASK;
+
+	req->in.h.opcode = FUSE_NOTIFY_REPLY;
+	req->in.h.nodeid = outarg->nodeid;
+	req->in.numargs = 2;
+	req->in.argpages = 1;
+	req->page_offset = offset;
+	req->end = fuse_retrieve_end;
+
+	index = outarg->offset >> PAGE_CACHE_SHIFT;
+	file_size = i_size_read(inode);
+	num = outarg->size;
+	if (outarg->offset > file_size)
+		num = 0;
+	else if (outarg->offset + num > file_size)
+		num = file_size - outarg->offset;
+
+	while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) {
+		struct page *page;
+		unsigned int this_num;
+
+		page = find_get_page(mapping, index);
+		if (!page)
+			break;
+
+		this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset);
+		req->pages[req->num_pages] = page;
+		req->num_pages++;
+
+		num -= this_num;
+		total_len += this_num;
+		index++;
+	}
+	req->misc.retrieve_in.offset = outarg->offset;
+	req->misc.retrieve_in.size = total_len;
+	req->in.args[0].size = sizeof(req->misc.retrieve_in);
+	req->in.args[0].value = &req->misc.retrieve_in;
+	req->in.args[1].size = total_len;
+
+	err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique);
+	if (err)
+		fuse_retrieve_end(fc, req);
+
+	return err;
+}
+
+static int fuse_notify_retrieve_from_inode(struct fuse_conn *fc,
+				struct fuse_notify_retrieve_out *outarg)
+{
+	struct inode *inode;
+	int err;
+
+	down_read(&fc->killsb);
+	err = -ENOENT;
+	if (fc->sb) {
+		u64 nodeid = outarg->nodeid;
+
+		inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid);
+		if (inode) {
+			err = fuse_retrieve(fc, inode, outarg);
+			iput(inode);
+		}
+	}
+	up_read(&fc->killsb);
+
+	return err;
+}
+
+static const struct fuse_conn_operations fuse_default_ops = {
+	.release = fuse_free_conn,
+	.notify_store = fuse_notify_store_to_inode,
+	.notify_retrieve = fuse_notify_retrieve_from_inode,
+};
+
 static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct fuse_conn *fc;
@@ -977,7 +1140,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 		fc->dont_mask = 1;
 	sb->s_flags |= MS_POSIXACL;
 
-	fc->release = fuse_free_conn;
+	fc->ops = &fuse_default_ops;
 	fc->flags = d.flags;
 	fc->user_id = d.user_id;
 	fc->group_id = d.group_id;
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 501e5cb..38b7a74 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -434,12 +434,12 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
 	if (error)
 		return error;
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (dsize > (dibh->b_size - sizeof(struct gfs2_dinode)))
 		dsize = (dibh->b_size - sizeof(struct gfs2_dinode));
 	memcpy(kaddr, dibh->b_data + sizeof(struct gfs2_dinode), dsize);
 	memset(kaddr + dsize, 0, PAGE_CACHE_SIZE - dsize);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	flush_dcache_page(page);
 	brelse(dibh);
 	SetPageUptodate(page);
@@ -542,9 +542,9 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
 		page = read_cache_page(mapping, index, __gfs2_readpage, NULL);
 		if (IS_ERR(page))
 			return PTR_ERR(page);
-		p = kmap_atomic(page, KM_USER0);
+		p = kmap_atomic(page);
 		memcpy(buf + copied, p + offset, amt);
-		kunmap_atomic(p, KM_USER0);
+		kunmap_atomic(p);
 		mark_page_accessed(page);
 		page_cache_release(page);
 		copied += amt;
@@ -788,11 +788,11 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
 	unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode);
 
 	BUG_ON((pos + len) > (dibh->b_size - sizeof(struct gfs2_dinode)));
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memcpy(buf + pos, kaddr + pos, copied);
 	memset(kaddr + pos + copied, 0, len - copied);
 	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (!PageUptodate(page))
 		SetPageUptodate(page);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index 0301be6..df7c6e8 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -553,11 +553,11 @@ static void gfs2_check_magic(struct buffer_head *bh)
 	__be32 *ptr;
 
 	clear_buffer_escaped(bh);
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	ptr = kaddr + bh_offset(bh);
 	if (*ptr == cpu_to_be32(GFS2_MAGIC))
 		set_buffer_escaped(bh);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
@@ -594,10 +594,10 @@ static void gfs2_write_blocks(struct gfs2_sbd *sdp, struct buffer_head *bh,
 		if (buffer_escaped(bd->bd_bh)) {
 			void *kaddr;
 			bh1 = gfs2_log_get_buf(sdp);
-			kaddr = kmap_atomic(bd->bd_bh->b_page, KM_USER0);
+			kaddr = kmap_atomic(bd->bd_bh->b_page);
 			memcpy(bh1->b_data, kaddr + bh_offset(bd->bd_bh),
 			       bh1->b_size);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			*(__be32 *)bh1->b_data = 0;
 			clear_buffer_escaped(bd->bd_bh);
 			unlock_buffer(bd->bd_bh);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index a45b21b..c0f8904 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -720,12 +720,12 @@ get_a_page:
 
 	gfs2_trans_add_bh(ip->i_gl, bh, 0);
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (offset + sizeof(struct gfs2_quota) > PAGE_CACHE_SIZE)
 		nbytes = PAGE_CACHE_SIZE - offset;
 	memcpy(kaddr + offset, ptr, nbytes);
 	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	unlock_page(page);
 	page_cache_release(page);
 
diff --git a/fs/inode.c b/fs/inode.c
index fb10d86..d3ebdbe 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1651,7 +1651,7 @@ __setup("ihash_entries=", set_ihash_entries);
  */
 void __init inode_init_early(void)
 {
-	int loop;
+	unsigned int loop;
 
 	/* If hashes are distributed across NUMA nodes, defer
 	 * hash allocation until vmalloc space is available.
@@ -1669,13 +1669,13 @@ void __init inode_init_early(void)
 					&i_hash_mask,
 					0);
 
-	for (loop = 0; loop < (1 << i_hash_shift); loop++)
+	for (loop = 0; loop < (1U << i_hash_shift); loop++)
 		INIT_HLIST_HEAD(&inode_hashtable[loop]);
 }
 
 void __init inode_init(void)
 {
-	int loop;
+	unsigned int loop;
 
 	/* inode slab cache */
 	inode_cachep = kmem_cache_create("inode_cache",
@@ -1699,7 +1699,7 @@ void __init inode_init(void)
 					&i_hash_mask,
 					0);
 
-	for (loop = 0; loop < (1 << i_hash_shift); loop++)
+	for (loop = 0; loop < (1U << i_hash_shift); loop++)
 		INIT_HLIST_HEAD(&inode_hashtable[loop]);
 }
 
diff --git a/fs/internal.h b/fs/internal.h
index 9962c59..0765acf 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -56,8 +56,7 @@ extern int sb_prepare_remount_readonly(struct super_block *);
 
 extern void __init mnt_init(void);
 
-DECLARE_BRLOCK(vfsmount_lock);
-
+extern struct lglock vfsmount_lock;
 
 /*
  * fs_struct.c
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 5d1a00a..05f0754 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -453,8 +453,6 @@ out:
  *
  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
  *
- * Called with the journal lock held.
- *
  * This is the only part of the journaling code which really needs to be
  * aware of transaction aborts.  Checkpointing involves writing to the
  * main filesystem area rather than to the journal, so it can proceed
@@ -472,13 +470,14 @@ int cleanup_journal_tail(journal_t *journal)
 	if (is_journal_aborted(journal))
 		return 1;
 
-	/* OK, work out the oldest transaction remaining in the log, and
+	/*
+	 * OK, work out the oldest transaction remaining in the log, and
 	 * the log block it starts at.
 	 *
 	 * If the log is now empty, we need to work out which is the
 	 * next transaction ID we will write, and where it will
-	 * start. */
-
+	 * start.
+	 */
 	spin_lock(&journal->j_state_lock);
 	spin_lock(&journal->j_list_lock);
 	transaction = journal->j_checkpoint_transactions;
@@ -504,7 +503,25 @@ int cleanup_journal_tail(journal_t *journal)
 		spin_unlock(&journal->j_state_lock);
 		return 1;
 	}
+	spin_unlock(&journal->j_state_lock);
+
+	/*
+	 * We need to make sure that any blocks that were recently written out
+	 * --- perhaps by log_do_checkpoint() --- are flushed out before we
+	 * drop the transactions from the journal. It's unlikely this will be
+	 * necessary, especially with an appropriately sized journal, but we
+	 * need this to guarantee correctness.  Fortunately
+	 * cleanup_journal_tail() doesn't get called all that often.
+	 */
+	if (journal->j_flags & JFS_BARRIER)
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 
+	spin_lock(&journal->j_state_lock);
+	if (!tid_gt(first_tid, journal->j_tail_sequence)) {
+		spin_unlock(&journal->j_state_lock);
+		/* Someone else cleaned up journal so return 0 */
+		return 0;
+	}
 	/* OK, update the superblock to recover the freed space.
 	 * Physical blocks come first: have we wrapped beyond the end of
 	 * the log?  */
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 59c09f9..e49e81b 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -328,7 +328,7 @@ repeat:
 		new_offset = offset_in_page(jh2bh(jh_in)->b_data);
 	}
 
-	mapped_data = kmap_atomic(new_page, KM_USER0);
+	mapped_data = kmap_atomic(new_page);
 	/*
 	 * Check for escaping
 	 */
@@ -337,7 +337,7 @@ repeat:
 		need_copy_out = 1;
 		do_escape = 1;
 	}
-	kunmap_atomic(mapped_data, KM_USER0);
+	kunmap_atomic(mapped_data);
 
 	/*
 	 * Do we need to do a data copy?
@@ -354,9 +354,9 @@ repeat:
 		}
 
 		jh_in->b_frozen_data = tmp;
-		mapped_data = kmap_atomic(new_page, KM_USER0);
+		mapped_data = kmap_atomic(new_page);
 		memcpy(tmp, mapped_data + new_offset, jh2bh(jh_in)->b_size);
-		kunmap_atomic(mapped_data, KM_USER0);
+		kunmap_atomic(mapped_data);
 
 		new_page = virt_to_page(tmp);
 		new_offset = offset_in_page(tmp);
@@ -368,9 +368,9 @@ repeat:
 	 * copying, we can finally do so.
 	 */
 	if (do_escape) {
-		mapped_data = kmap_atomic(new_page, KM_USER0);
+		mapped_data = kmap_atomic(new_page);
 		*((unsigned int *)(mapped_data + new_offset)) = 0;
-		kunmap_atomic(mapped_data, KM_USER0);
+		kunmap_atomic(mapped_data);
 	}
 
 	set_bh_page(new_bh, new_page, new_offset);
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 5b43e96..008bf06 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/jbd.h>
 #include <linux/errno.h>
+#include <linux/blkdev.h>
 #endif
 
 /*
@@ -263,6 +264,9 @@ int journal_recover(journal_t *journal)
 	err2 = sync_blockdev(journal->j_fs_dev);
 	if (!err)
 		err = err2;
+	/* Flush disk caches to get replayed data on the permanent storage */
+	if (journal->j_flags & JFS_BARRIER)
+		blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
 
 	return err;
 }
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 7fce94b..b2a7e52 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -718,9 +718,9 @@ done:
 			    "Possible IO failure.\n");
 		page = jh2bh(jh)->b_page;
 		offset = offset_in_page(jh2bh(jh)->b_data);
-		source = kmap_atomic(page, KM_USER0);
+		source = kmap_atomic(page);
 		memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
-		kunmap_atomic(source, KM_USER0);
+		kunmap_atomic(source);
 	}
 	jbd_unlock_bh_state(bh);
 
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 5069b84..c067a8c 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -286,10 +286,10 @@ static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh)
 	char *addr;
 	__u32 checksum;
 
-	addr = kmap_atomic(page, KM_USER0);
+	addr = kmap_atomic(page);
 	checksum = crc32_be(crc32_sum,
 		(void *)(addr + offset_in_page(bh->b_data)), bh->b_size);
-	kunmap_atomic(addr, KM_USER0);
+	kunmap_atomic(addr);
 
 	return checksum;
 }
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index c0a5f9f..5ff8940 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -345,7 +345,7 @@ repeat:
 		new_offset = offset_in_page(jh2bh(jh_in)->b_data);
 	}
 
-	mapped_data = kmap_atomic(new_page, KM_USER0);
+	mapped_data = kmap_atomic(new_page);
 	/*
 	 * Fire data frozen trigger if data already wasn't frozen.  Do this
 	 * before checking for escaping, as the trigger may modify the magic
@@ -364,7 +364,7 @@ repeat:
 		need_copy_out = 1;
 		do_escape = 1;
 	}
-	kunmap_atomic(mapped_data, KM_USER0);
+	kunmap_atomic(mapped_data);
 
 	/*
 	 * Do we need to do a data copy?
@@ -385,9 +385,9 @@ repeat:
 		}
 
 		jh_in->b_frozen_data = tmp;
-		mapped_data = kmap_atomic(new_page, KM_USER0);
+		mapped_data = kmap_atomic(new_page);
 		memcpy(tmp, mapped_data + new_offset, jh2bh(jh_in)->b_size);
-		kunmap_atomic(mapped_data, KM_USER0);
+		kunmap_atomic(mapped_data);
 
 		new_page = virt_to_page(tmp);
 		new_offset = offset_in_page(tmp);
@@ -406,9 +406,9 @@ repeat:
 	 * copying, we can finally do so.
 	 */
 	if (do_escape) {
-		mapped_data = kmap_atomic(new_page, KM_USER0);
+		mapped_data = kmap_atomic(new_page);
 		*((unsigned int *)(mapped_data + new_offset)) = 0;
-		kunmap_atomic(mapped_data, KM_USER0);
+		kunmap_atomic(mapped_data);
 	}
 
 	set_bh_page(new_bh, new_page, new_offset);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 35ae096..e5aba56 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -783,12 +783,12 @@ done:
 			    "Possible IO failure.\n");
 		page = jh2bh(jh)->b_page;
 		offset = offset_in_page(jh2bh(jh)->b_data);
-		source = kmap_atomic(page, KM_USER0);
+		source = kmap_atomic(page);
 		/* Fire data frozen trigger just before we copy the data */
 		jbd2_buffer_frozen_trigger(jh, source + offset,
 					   jh->b_triggers);
 		memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size);
-		kunmap_atomic(source, KM_USER0);
+		kunmap_atomic(source);
 
 		/*
 		 * Now that the frozen data is saved off, we need to store
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index a01cdad..eafb8d3 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
 	void *ebuf;
 	uint32_t ofs;
 	size_t retlen;
-	int ret = -EIO;
+	int ret;
 	unsigned long *wordebuf;
 
 	ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen,
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index e97404d..8efe984 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -152,14 +152,13 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs)
 	filler_t *filler = logfs_mtd_readpage;
 	struct mtd_info *mtd = super->s_mtd;
 
-	if (!mtd_can_have_bb(mtd))
-		return NULL;
-
 	*ofs = 0;
-	while (mtd_block_isbad(mtd, *ofs)) {
-		*ofs += mtd->erasesize;
-		if (*ofs >= mtd->size)
-			return NULL;
+	if (mtd_can_have_bb(mtd)) {
+		while (mtd_block_isbad(mtd, *ofs)) {
+			*ofs += mtd->erasesize;
+			if (*ofs >= mtd->size)
+				return NULL;
+		}
 	}
 	BUG_ON(*ofs & ~PAGE_MASK);
 	return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb);
@@ -172,14 +171,13 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs)
 	filler_t *filler = logfs_mtd_readpage;
 	struct mtd_info *mtd = super->s_mtd;
 
-	if (!mtd_can_have_bb(mtd))
-		return NULL;
-
 	*ofs = mtd->size - mtd->erasesize;
-	while (mtd_block_isbad(mtd, *ofs)) {
-		*ofs -= mtd->erasesize;
-		if (*ofs <= 0)
-			return NULL;
+	if (mtd_can_have_bb(mtd)) {
+		while (mtd_block_isbad(mtd, *ofs)) {
+			*ofs -= mtd->erasesize;
+			if (*ofs <= 0)
+				return NULL;
+		}
 	}
 	*ofs = *ofs + mtd->erasesize - 0x1000;
 	BUG_ON(*ofs & ~PAGE_MASK);
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 501043e..1b6e21d 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -71,7 +71,7 @@ static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
 
 static int write_inode(struct inode *inode)
 {
-	return __logfs_write_inode(inode, WF_LOCK);
+	return __logfs_write_inode(inode, NULL, WF_LOCK);
 }
 
 static s64 dir_seek_data(struct inode *inode, s64 pos)
@@ -177,17 +177,17 @@ static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry)
 				(filler_t *)logfs_readpage, NULL);
 		if (IS_ERR(page))
 			return page;
-		dd = kmap_atomic(page, KM_USER0);
+		dd = kmap_atomic(page);
 		BUG_ON(dd->namelen == 0);
 
 		if (name->len != be16_to_cpu(dd->namelen) ||
 				memcmp(name->name, dd->name, name->len)) {
-			kunmap_atomic(dd, KM_USER0);
+			kunmap_atomic(dd);
 			page_cache_release(page);
 			continue;
 		}
 
-		kunmap_atomic(dd, KM_USER0);
+		kunmap_atomic(dd);
 		return page;
 	}
 	return NULL;
@@ -365,9 +365,9 @@ static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
 		return NULL;
 	}
 	index = page->index;
-	dd = kmap_atomic(page, KM_USER0);
+	dd = kmap_atomic(page);
 	ino = be64_to_cpu(dd->ino);
-	kunmap_atomic(dd, KM_USER0);
+	kunmap_atomic(dd);
 	page_cache_release(page);
 
 	inode = logfs_iget(dir->i_sb, ino);
@@ -402,12 +402,12 @@ static int logfs_write_dir(struct inode *dir, struct dentry *dentry,
 		if (!page)
 			return -ENOMEM;
 
-		dd = kmap_atomic(page, KM_USER0);
+		dd = kmap_atomic(page);
 		memset(dd, 0, sizeof(*dd));
 		dd->ino = cpu_to_be64(inode->i_ino);
 		dd->type = logfs_type(inode);
 		logfs_set_name(dd, &dentry->d_name);
-		kunmap_atomic(dd, KM_USER0);
+		kunmap_atomic(dd);
 
 		err = logfs_write_buf(dir, page, WF_LOCK);
 		unlock_page(page);
@@ -579,9 +579,9 @@ static int logfs_get_dd(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(page))
 		return PTR_ERR(page);
 	*pos = page->index;
-	map = kmap_atomic(page, KM_USER0);
+	map = kmap_atomic(page);
 	memcpy(dd, map, sizeof(*dd));
-	kunmap_atomic(map, KM_USER0);
+	kunmap_atomic(map);
 	page_cache_release(page);
 	return 0;
 }
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index b548c87..3886cde 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -230,7 +230,9 @@ int logfs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 		return ret;
 
 	mutex_lock(&inode->i_mutex);
+	logfs_get_wblocks(sb, NULL, WF_LOCK);
 	logfs_write_anchor(sb);
+	logfs_put_wblocks(sb, NULL, WF_LOCK);
 	mutex_unlock(&inode->i_mutex);
 
 	return 0;
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index caa4419..d4efb06 100644
--- a/fs/logfs/gc.c
+++ b/fs/logfs/gc.c
@@ -367,7 +367,7 @@ static struct gc_candidate *get_candidate(struct super_block *sb)
 	int i, max_dist;
 	struct gc_candidate *cand = NULL, *this;
 
-	max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+	max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
 
 	for (i = max_dist; i >= 0; i--) {
 		this = first_in_list(&super->s_low_list[i]);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 388df1a..a422f42 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -286,7 +286,7 @@ static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
 		return 0;
 
-	ret = __logfs_write_inode(inode, flags);
+	ret = __logfs_write_inode(inode, NULL, flags);
 	LOGFS_BUG_ON(ret, inode->i_sb);
 	return ret;
 }
@@ -363,7 +363,9 @@ static void logfs_init_once(void *_li)
 
 static int logfs_sync_fs(struct super_block *sb, int wait)
 {
+	logfs_get_wblocks(sb, NULL, WF_LOCK);
 	logfs_write_anchor(sb);
+	logfs_put_wblocks(sb, NULL, WF_LOCK);
 	return 0;
 }
 
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index 9da2970..1e1c369 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -612,7 +612,6 @@ static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
 	if (len == 0)
 		return logfs_write_header(super, header, 0, type);
 
-	BUG_ON(len > sb->s_blocksize);
 	compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
 	if (compr_len < 0 || type == JE_ANCHOR) {
 		memcpy(data, buf, len);
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 9263738..5f09376 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -528,7 +528,7 @@ void logfs_destroy_inode_cache(void);
 void logfs_set_blocks(struct inode *inode, u64 no);
 /* these logically belong into inode.c but actually reside in readwrite.c */
 int logfs_read_inode(struct inode *inode);
-int __logfs_write_inode(struct inode *inode, long flags);
+int __logfs_write_inode(struct inode *inode, struct page *, long flags);
 void logfs_evict_inode(struct inode *inode);
 
 /* journal.c */
@@ -577,6 +577,8 @@ void initialize_block_counters(struct page *page, struct logfs_block *block,
 		__be64 *array, int page_is_empty);
 int logfs_exist_block(struct inode *inode, u64 bix);
 int get_page_reserve(struct inode *inode, struct page *page);
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
 extern struct logfs_block_ops indirect_block_ops;
 
 /* segment.c */
@@ -594,6 +596,7 @@ int logfs_init_mapping(struct super_block *sb);
 void logfs_sync_area(struct logfs_area *area);
 void logfs_sync_segments(struct super_block *sb);
 void freeseg(struct super_block *sb, u32 segno);
+void free_areas(struct super_block *sb);
 
 /* area handling */
 int logfs_init_areas(struct super_block *sb);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 2ac4217..e3ab5e5 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -244,8 +244,7 @@ static void preunlock_page(struct super_block *sb, struct page *page, int lock)
  * is waiting for s_write_mutex.  We annotate this fact by setting PG_pre_locked
  * in addition to PG_locked.
  */
-static void logfs_get_wblocks(struct super_block *sb, struct page *page,
-		int lock)
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
 {
 	struct logfs_super *super = logfs_super(sb);
 
@@ -260,8 +259,7 @@ static void logfs_get_wblocks(struct super_block *sb, struct page *page,
 	}
 }
 
-static void logfs_put_wblocks(struct super_block *sb, struct page *page,
-		int lock)
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
 {
 	struct logfs_super *super = logfs_super(sb);
 
@@ -424,7 +422,7 @@ static void inode_write_block(struct logfs_block *block)
 	if (inode->i_ino == LOGFS_INO_MASTER)
 		logfs_write_anchor(inode->i_sb);
 	else {
-		ret = __logfs_write_inode(inode, 0);
+		ret = __logfs_write_inode(inode, NULL, 0);
 		/* see indirect_write_block comment */
 		BUG_ON(ret);
 	}
@@ -519,9 +517,9 @@ static int indirect_write_alias(struct super_block *sb,
 
 		ino = page->mapping->host->i_ino;
 		logfs_unpack_index(page->index, &bix, &level);
-		child = kmap_atomic(page, KM_USER0);
+		child = kmap_atomic(page);
 		val = child[pos];
-		kunmap_atomic(child, KM_USER0);
+		kunmap_atomic(child);
 		err = write_one_alias(sb, ino, bix, level, pos, val);
 		if (err)
 			return err;
@@ -560,8 +558,13 @@ static void inode_free_block(struct super_block *sb, struct logfs_block *block)
 static void indirect_free_block(struct super_block *sb,
 		struct logfs_block *block)
 {
-	ClearPagePrivate(block->page);
-	block->page->private = 0;
+	struct page *page = block->page;
+
+	if (PagePrivate(page)) {
+		ClearPagePrivate(page);
+		page_cache_release(page);
+		set_page_private(page, 0);
+	}
 	__free_block(sb, block);
 }
 
@@ -650,8 +653,11 @@ static void alloc_data_block(struct inode *inode, struct page *page)
 	logfs_unpack_index(page->index, &bix, &level);
 	block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
 	block->page = page;
+
 	SetPagePrivate(page);
-	page->private = (unsigned long)block;
+	page_cache_get(page);
+	set_page_private(page, (unsigned long) block);
+
 	block->ops = &indirect_block_ops;
 }
 
@@ -667,9 +673,9 @@ static void alloc_indirect_block(struct inode *inode, struct page *page,
 	alloc_data_block(inode, page);
 
 	block = logfs_block(page);
-	array = kmap_atomic(page, KM_USER0);
+	array = kmap_atomic(page);
 	initialize_block_counters(page, block, array, page_is_empty);
-	kunmap_atomic(array, KM_USER0);
+	kunmap_atomic(array);
 }
 
 static void block_set_pointer(struct page *page, int index, u64 ptr)
@@ -679,10 +685,10 @@ static void block_set_pointer(struct page *page, int index, u64 ptr)
 	u64 oldptr;
 
 	BUG_ON(!block);
-	array = kmap_atomic(page, KM_USER0);
+	array = kmap_atomic(page);
 	oldptr = be64_to_cpu(array[index]);
 	array[index] = cpu_to_be64(ptr);
-	kunmap_atomic(array, KM_USER0);
+	kunmap_atomic(array);
 	SetPageUptodate(page);
 
 	block->full += !!(ptr & LOGFS_FULLY_POPULATED)
@@ -695,9 +701,9 @@ static u64 block_get_pointer(struct page *page, int index)
 	__be64 *block;
 	u64 ptr;
 
-	block = kmap_atomic(page, KM_USER0);
+	block = kmap_atomic(page);
 	ptr = be64_to_cpu(block[index]);
-	kunmap_atomic(block, KM_USER0);
+	kunmap_atomic(block);
 	return ptr;
 }
 
@@ -844,7 +850,7 @@ static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)
 		}
 
 		slot = get_bits(bix, SUBLEVEL(level));
-		rblock = kmap_atomic(page, KM_USER0);
+		rblock = kmap_atomic(page);
 		while (slot < LOGFS_BLOCK_FACTOR) {
 			if (data && (rblock[slot] != 0))
 				break;
@@ -855,12 +861,12 @@ static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)
 			bix &= ~(increment - 1);
 		}
 		if (slot >= LOGFS_BLOCK_FACTOR) {
-			kunmap_atomic(rblock, KM_USER0);
+			kunmap_atomic(rblock);
 			logfs_put_read_page(page);
 			return bix;
 		}
 		bofs = be64_to_cpu(rblock[slot]);
-		kunmap_atomic(rblock, KM_USER0);
+		kunmap_atomic(rblock);
 		logfs_put_read_page(page);
 		if (!bofs) {
 			BUG_ON(data);
@@ -1570,11 +1576,15 @@ int logfs_write_buf(struct inode *inode, struct page *page, long flags)
 static int __logfs_delete(struct inode *inode, struct page *page)
 {
 	long flags = WF_DELETE;
+	int err;
 
 	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
 
 	if (page->index < I0_BLOCKS)
 		return logfs_write_direct(inode, page, flags);
+	err = grow_inode(inode, page->index, 0);
+	if (err)
+		return err;
 	return logfs_write_rec(inode, page, page->index, 0, flags);
 }
 
@@ -1623,7 +1633,7 @@ int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
 			if (inode->i_ino == LOGFS_INO_MASTER)
 				logfs_write_anchor(inode->i_sb);
 			else {
-				err = __logfs_write_inode(inode, flags);
+				err = __logfs_write_inode(inode, page, flags);
 			}
 		}
 	}
@@ -1873,7 +1883,7 @@ int logfs_truncate(struct inode *inode, u64 target)
 		logfs_get_wblocks(sb, NULL, 1);
 		err = __logfs_truncate(inode, size);
 		if (!err)
-			err = __logfs_write_inode(inode, 0);
+			err = __logfs_write_inode(inode, NULL, 0);
 		logfs_put_wblocks(sb, NULL, 1);
 	}
 
@@ -1901,8 +1911,11 @@ static void move_page_to_inode(struct inode *inode, struct page *page)
 	li->li_block = block;
 
 	block->page = NULL;
-	page->private = 0;
-	ClearPagePrivate(page);
+	if (PagePrivate(page)) {
+		ClearPagePrivate(page);
+		page_cache_release(page);
+		set_page_private(page, 0);
+	}
 }
 
 static void move_inode_to_page(struct page *page, struct inode *inode)
@@ -1918,8 +1931,12 @@ static void move_inode_to_page(struct page *page, struct inode *inode)
 	BUG_ON(PagePrivate(page));
 	block->ops = &indirect_block_ops;
 	block->page = page;
-	page->private = (unsigned long)block;
-	SetPagePrivate(page);
+
+	if (!PagePrivate(page)) {
+		SetPagePrivate(page);
+		page_cache_get(page);
+		set_page_private(page, (unsigned long) block);
+	}
 
 	block->inode = NULL;
 	li->li_block = NULL;
@@ -1944,9 +1961,9 @@ int logfs_read_inode(struct inode *inode)
 	if (IS_ERR(page))
 		return PTR_ERR(page);
 
-	di = kmap_atomic(page, KM_USER0);
+	di = kmap_atomic(page);
 	logfs_disk_to_inode(di, inode);
-	kunmap_atomic(di, KM_USER0);
+	kunmap_atomic(di);
 	move_page_to_inode(inode, page);
 	page_cache_release(page);
 	return 0;
@@ -1965,9 +1982,9 @@ static struct page *inode_to_page(struct inode *inode)
 	if (!page)
 		return NULL;
 
-	di = kmap_atomic(page, KM_USER0);
+	di = kmap_atomic(page);
 	logfs_inode_to_disk(inode, di);
-	kunmap_atomic(di, KM_USER0);
+	kunmap_atomic(di);
 	move_inode_to_page(page, inode);
 	return page;
 }
@@ -2024,13 +2041,13 @@ static void logfs_mod_segment_entry(struct super_block *sb, u32 segno,
 
 	if (write)
 		alloc_indirect_block(inode, page, 0);
-	se = kmap_atomic(page, KM_USER0);
+	se = kmap_atomic(page);
 	change_se(se + child_no, arg);
 	if (write) {
 		logfs_set_alias(sb, logfs_block(page), child_no);
 		BUG_ON((int)be32_to_cpu(se[child_no].valid) > super->s_segsize);
 	}
-	kunmap_atomic(se, KM_USER0);
+	kunmap_atomic(se);
 
 	logfs_put_write_page(page);
 }
@@ -2106,14 +2123,14 @@ void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
 			ec_level);
 }
 
-int __logfs_write_inode(struct inode *inode, long flags)
+int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
 {
 	struct super_block *sb = inode->i_sb;
 	int ret;
 
-	logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+	logfs_get_wblocks(sb, page, flags & WF_LOCK);
 	ret = do_write_inode(inode);
-	logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+	logfs_put_wblocks(sb, page, flags & WF_LOCK);
 	return ret;
 }
 
@@ -2228,10 +2245,10 @@ int logfs_inode_write(struct inode *inode, const void *buf, size_t count,
 	if (!page)
 		return -ENOMEM;
 
-	pagebuf = kmap_atomic(page, KM_USER0);
+	pagebuf = kmap_atomic(page);
 	memcpy(pagebuf, buf, count);
 	flush_dcache_page(page);
-	kunmap_atomic(pagebuf, KM_USER0);
+	kunmap_atomic(pagebuf);
 
 	if (i_size_read(inode) < pos + LOGFS_BLOCKSIZE)
 		i_size_write(inode, pos + LOGFS_BLOCKSIZE);
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 9d51873..e28d090 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -86,7 +86,11 @@ int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
 		BUG_ON(!page); /* FIXME: reserve a pool */
 		SetPageUptodate(page);
 		memcpy(page_address(page) + offset, buf, copylen);
-		SetPagePrivate(page);
+
+		if (!PagePrivate(page)) {
+			SetPagePrivate(page);
+			page_cache_get(page);
+		}
 		page_cache_release(page);
 
 		buf += copylen;
@@ -110,7 +114,10 @@ static void pad_partial_page(struct logfs_area *area)
 		page = get_mapping_page(sb, index, 0);
 		BUG_ON(!page); /* FIXME: reserve a pool */
 		memset(page_address(page) + offset, 0xff, len);
-		SetPagePrivate(page);
+		if (!PagePrivate(page)) {
+			SetPagePrivate(page);
+			page_cache_get(page);
+		}
 		page_cache_release(page);
 	}
 }
@@ -130,7 +137,10 @@ static void pad_full_pages(struct logfs_area *area)
 		BUG_ON(!page); /* FIXME: reserve a pool */
 		SetPageUptodate(page);
 		memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
-		SetPagePrivate(page);
+		if (!PagePrivate(page)) {
+			SetPagePrivate(page);
+			page_cache_get(page);
+		}
 		page_cache_release(page);
 		index++;
 		no_indizes--;
@@ -485,8 +495,12 @@ static void move_btree_to_page(struct inode *inode, struct page *page,
 		mempool_free(item, super->s_alias_pool);
 	}
 	block->page = page;
-	SetPagePrivate(page);
-	page->private = (unsigned long)block;
+
+	if (!PagePrivate(page)) {
+		SetPagePrivate(page);
+		page_cache_get(page);
+		set_page_private(page, (unsigned long) block);
+	}
 	block->ops = &indirect_block_ops;
 	initialize_block_counters(page, block, data, 0);
 }
@@ -529,15 +543,19 @@ void move_page_to_btree(struct page *page)
 		BUG_ON(!item); /* mempool empty */
 		memset(item, 0, sizeof(*item));
 
-		child = kmap_atomic(page, KM_USER0);
+		child = kmap_atomic(page);
 		item->val = child[pos];
-		kunmap_atomic(child, KM_USER0);
+		kunmap_atomic(child);
 		item->child_no = pos;
 		list_add(&item->list, &block->item_list);
 	}
 	block->page = NULL;
-	ClearPagePrivate(page);
-	page->private = 0;
+
+	if (PagePrivate(page)) {
+		ClearPagePrivate(page);
+		page_cache_release(page);
+		set_page_private(page, 0);
+	}
 	block->ops = &btree_block_ops;
 	err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
 			block);
@@ -702,7 +720,10 @@ void freeseg(struct super_block *sb, u32 segno)
 		page = find_get_page(mapping, ofs >> PAGE_SHIFT);
 		if (!page)
 			continue;
-		ClearPagePrivate(page);
+		if (PagePrivate(page)) {
+			ClearPagePrivate(page);
+			page_cache_release(page);
+		}
 		page_cache_release(page);
 	}
 }
@@ -841,6 +862,16 @@ static void free_area(struct logfs_area *area)
 	kfree(area);
 }
 
+void free_areas(struct super_block *sb)
+{
+	struct logfs_super *super = logfs_super(sb);
+	int i;
+
+	for_each_area(i)
+		free_area(super->s_area[i]);
+	free_area(super->s_journal_area);
+}
+
 static struct logfs_area *alloc_area(struct super_block *sb)
 {
 	struct logfs_area *area;
@@ -923,10 +954,6 @@ err:
 void logfs_cleanup_areas(struct super_block *sb)
 {
 	struct logfs_super *super = logfs_super(sb);
-	int i;
 
 	btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
-	for_each_area(i)
-		free_area(super->s_area[i]);
-	free_area(super->s_journal_area);
 }
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index e795c234..c9ee7f5 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -486,14 +486,15 @@ static void logfs_kill_sb(struct super_block *sb)
 	/* Alias entries slow down mount, so evict as many as possible */
 	sync_filesystem(sb);
 	logfs_write_anchor(sb);
+	free_areas(sb);
 
 	/*
 	 * From this point on alias entries are simply dropped - and any
 	 * writes to the object store are considered bugs.
 	 */
-	super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
 	log_super("LogFS: Now in shutdown\n");
 	generic_shutdown_super(sb);
+	super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
 
 	BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
 
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 085a926..685b2d9 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -335,7 +335,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
 		goto fail;
 	}
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memset(kaddr, 0, PAGE_CACHE_SIZE);
 
 	if (sbi->s_version == MINIX_V3) {
@@ -355,7 +355,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir)
 		de->inode = dir->i_ino;
 		strcpy(de->name, "..");
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
 fail:
diff --git a/fs/namei.c b/fs/namei.c
index 208c6aa..7a06bdf 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -462,7 +462,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
 	mntget(nd->path.mnt);
 
 	rcu_read_unlock();
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 	nd->flags &= ~LOOKUP_RCU;
 	return 0;
 
@@ -520,14 +520,14 @@ static int complete_walk(struct nameidata *nd)
 		if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
 			spin_unlock(&dentry->d_lock);
 			rcu_read_unlock();
-			br_read_unlock(vfsmount_lock);
+			br_read_unlock(&vfsmount_lock);
 			return -ECHILD;
 		}
 		BUG_ON(nd->inode != dentry->d_inode);
 		spin_unlock(&dentry->d_lock);
 		mntget(nd->path.mnt);
 		rcu_read_unlock();
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 	}
 
 	if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -694,15 +694,15 @@ int follow_up(struct path *path)
 	struct mount *parent;
 	struct dentry *mountpoint;
 
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	parent = mnt->mnt_parent;
 	if (&parent->mnt == path->mnt) {
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 		return 0;
 	}
 	mntget(&parent->mnt);
 	mountpoint = dget(mnt->mnt_mountpoint);
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 	dput(path->dentry);
 	path->dentry = mountpoint;
 	mntput(path->mnt);
@@ -960,7 +960,7 @@ failed:
 	if (!(nd->flags & LOOKUP_ROOT))
 		nd->root.mnt = NULL;
 	rcu_read_unlock();
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 	return -ECHILD;
 }
 
@@ -1254,7 +1254,7 @@ static void terminate_walk(struct nameidata *nd)
 		if (!(nd->flags & LOOKUP_ROOT))
 			nd->root.mnt = NULL;
 		rcu_read_unlock();
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 	}
 }
 
@@ -1488,7 +1488,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 		nd->path = nd->root;
 		nd->inode = inode;
 		if (flags & LOOKUP_RCU) {
-			br_read_lock(vfsmount_lock);
+			br_read_lock(&vfsmount_lock);
 			rcu_read_lock();
 			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
 		} else {
@@ -1501,7 +1501,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 
 	if (*name=='/') {
 		if (flags & LOOKUP_RCU) {
-			br_read_lock(vfsmount_lock);
+			br_read_lock(&vfsmount_lock);
 			rcu_read_lock();
 			set_root_rcu(nd);
 		} else {
@@ -1514,7 +1514,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 			struct fs_struct *fs = current->fs;
 			unsigned seq;
 
-			br_read_lock(vfsmount_lock);
+			br_read_lock(&vfsmount_lock);
 			rcu_read_lock();
 
 			do {
@@ -1550,7 +1550,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 			if (fput_needed)
 				*fp = file;
 			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-			br_read_lock(vfsmount_lock);
+			br_read_lock(&vfsmount_lock);
 			rcu_read_lock();
 		} else {
 			path_get(&file->f_path);
@@ -3347,9 +3347,9 @@ retry:
 	if (err)
 		goto fail;
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memcpy(kaddr, symname, len-1);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
 							page, fsdata);
diff --git a/fs/namespace.c b/fs/namespace.c
index e608199..5a6208b 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -397,7 +397,7 @@ static int mnt_make_readonly(struct mount *mnt)
 {
 	int ret = 0;
 
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
 	/*
 	 * After storing MNT_WRITE_HOLD, we'll read the counters. This store
@@ -431,15 +431,15 @@ static int mnt_make_readonly(struct mount *mnt)
 	 */
 	smp_wmb();
 	mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	return ret;
 }
 
 static void __mnt_unmake_readonly(struct mount *mnt)
 {
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	mnt->mnt.mnt_flags &= ~MNT_READONLY;
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 }
 
 int sb_prepare_remount_readonly(struct super_block *sb)
@@ -451,7 +451,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
 	if (atomic_long_read(&sb->s_remove_count))
 		return -EBUSY;
 
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
 		if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
 			mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
@@ -473,7 +473,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
 		if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
 			mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 
 	return err;
 }
@@ -522,14 +522,14 @@ struct vfsmount *lookup_mnt(struct path *path)
 {
 	struct mount *child_mnt;
 
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
 	if (child_mnt) {
 		mnt_add_count(child_mnt, 1);
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 		return &child_mnt->mnt;
 	} else {
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 		return NULL;
 	}
 }
@@ -714,9 +714,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
 	mnt->mnt.mnt_sb = root->d_sb;
 	mnt->mnt_mountpoint = mnt->mnt.mnt_root;
 	mnt->mnt_parent = mnt;
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	return &mnt->mnt;
 }
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
@@ -745,9 +745,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 		mnt->mnt.mnt_root = dget(root);
 		mnt->mnt_mountpoint = mnt->mnt.mnt_root;
 		mnt->mnt_parent = mnt;
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 
 		if (flag & CL_SLAVE) {
 			list_add(&mnt->mnt_slave, &old->mnt_slave_list);
@@ -803,35 +803,36 @@ static void mntput_no_expire(struct mount *mnt)
 {
 put_again:
 #ifdef CONFIG_SMP
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	if (likely(atomic_read(&mnt->mnt_longterm))) {
 		mnt_add_count(mnt, -1);
-		br_read_unlock(vfsmount_lock);
+		br_read_unlock(&vfsmount_lock);
 		return;
 	}
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	mnt_add_count(mnt, -1);
 	if (mnt_get_count(mnt)) {
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 		return;
 	}
 #else
 	mnt_add_count(mnt, -1);
 	if (likely(mnt_get_count(mnt)))
 		return;
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 #endif
 	if (unlikely(mnt->mnt_pinned)) {
 		mnt_add_count(mnt, mnt->mnt_pinned + 1);
 		mnt->mnt_pinned = 0;
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 		acct_auto_close_mnt(&mnt->mnt);
 		goto put_again;
 	}
+
 	list_del(&mnt->mnt_instance);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	mntfree(mnt);
 }
 
@@ -857,21 +858,21 @@ EXPORT_SYMBOL(mntget);
 
 void mnt_pin(struct vfsmount *mnt)
 {
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	real_mount(mnt)->mnt_pinned++;
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 }
 EXPORT_SYMBOL(mnt_pin);
 
 void mnt_unpin(struct vfsmount *m)
 {
 	struct mount *mnt = real_mount(m);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	if (mnt->mnt_pinned) {
 		mnt_add_count(mnt, 1);
 		mnt->mnt_pinned--;
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 }
 EXPORT_SYMBOL(mnt_unpin);
 
@@ -988,12 +989,12 @@ int may_umount_tree(struct vfsmount *m)
 	BUG_ON(!m);
 
 	/* write lock needed for mnt_get_count */
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	for (p = mnt; p; p = next_mnt(p, mnt)) {
 		actual_refs += mnt_get_count(p);
 		minimum_refs += 2;
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 
 	if (actual_refs > minimum_refs)
 		return 0;
@@ -1020,10 +1021,10 @@ int may_umount(struct vfsmount *mnt)
 {
 	int ret = 1;
 	down_read(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	if (propagate_mount_busy(real_mount(mnt), 2))
 		ret = 0;
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_read(&namespace_sem);
 	return ret;
 }
@@ -1040,13 +1041,13 @@ void release_mounts(struct list_head *head)
 			struct dentry *dentry;
 			struct mount *m;
 
-			br_write_lock(vfsmount_lock);
+			br_write_lock(&vfsmount_lock);
 			dentry = mnt->mnt_mountpoint;
 			m = mnt->mnt_parent;
 			mnt->mnt_mountpoint = mnt->mnt.mnt_root;
 			mnt->mnt_parent = mnt;
 			m->mnt_ghosts--;
-			br_write_unlock(vfsmount_lock);
+			br_write_unlock(&vfsmount_lock);
 			dput(dentry);
 			mntput(&m->mnt);
 		}
@@ -1112,12 +1113,12 @@ static int do_umount(struct mount *mnt, int flags)
 		 * probably don't strictly need the lock here if we examined
 		 * all race cases, but it's a slowpath.
 		 */
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		if (mnt_get_count(mnt) != 2) {
-			br_write_unlock(vfsmount_lock);
+			br_write_unlock(&vfsmount_lock);
 			return -EBUSY;
 		}
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 
 		if (!xchg(&mnt->mnt_expiry_mark, 1))
 			return -EAGAIN;
@@ -1159,7 +1160,7 @@ static int do_umount(struct mount *mnt, int flags)
 	}
 
 	down_write(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	event++;
 
 	if (!(flags & MNT_DETACH))
@@ -1171,7 +1172,7 @@ static int do_umount(struct mount *mnt, int flags)
 			umount_tree(mnt, 1, &umount_list);
 		retval = 0;
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
 	return retval;
@@ -1286,19 +1287,19 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
 			q = clone_mnt(p, p->mnt.mnt_root, flag);
 			if (!q)
 				goto Enomem;
-			br_write_lock(vfsmount_lock);
+			br_write_lock(&vfsmount_lock);
 			list_add_tail(&q->mnt_list, &res->mnt_list);
 			attach_mnt(q, &path);
-			br_write_unlock(vfsmount_lock);
+			br_write_unlock(&vfsmount_lock);
 		}
 	}
 	return res;
 Enomem:
 	if (res) {
 		LIST_HEAD(umount_list);
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		umount_tree(res, 0, &umount_list);
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 		release_mounts(&umount_list);
 	}
 	return NULL;
@@ -1318,9 +1319,9 @@ void drop_collected_mounts(struct vfsmount *mnt)
 {
 	LIST_HEAD(umount_list);
 	down_write(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	umount_tree(real_mount(mnt), 0, &umount_list);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
 }
@@ -1448,7 +1449,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	if (err)
 		goto out_cleanup_ids;
 
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 
 	if (IS_MNT_SHARED(dest_mnt)) {
 		for (p = source_mnt; p; p = next_mnt(p, source_mnt))
@@ -1467,7 +1468,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 		list_del_init(&child->mnt_hash);
 		commit_tree(child);
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 
 	return 0;
 
@@ -1565,10 +1566,10 @@ static int do_change_type(struct path *path, int flag)
 			goto out_unlock;
 	}
 
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
 		change_mnt_propagation(m, type);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 
  out_unlock:
 	up_write(&namespace_sem);
@@ -1617,9 +1618,9 @@ static int do_loopback(struct path *path, char *old_name,
 
 	err = graft_tree(mnt, path);
 	if (err) {
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		umount_tree(mnt, 0, &umount_list);
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 	}
 out2:
 	unlock_mount(path);
@@ -1677,16 +1678,16 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	else
 		err = do_remount_sb(sb, flags, data, 0);
 	if (!err) {
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
 		mnt->mnt.mnt_flags = mnt_flags;
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 	}
 	up_write(&sb->s_umount);
 	if (!err) {
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		touch_mnt_namespace(mnt->mnt_ns);
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 	}
 	return err;
 }
@@ -1893,9 +1894,9 @@ fail:
 	/* remove m from any expiration list it may be on */
 	if (!list_empty(&mnt->mnt_expire)) {
 		down_write(&namespace_sem);
-		br_write_lock(vfsmount_lock);
+		br_write_lock(&vfsmount_lock);
 		list_del_init(&mnt->mnt_expire);
-		br_write_unlock(vfsmount_lock);
+		br_write_unlock(&vfsmount_lock);
 		up_write(&namespace_sem);
 	}
 	mntput(m);
@@ -1911,11 +1912,11 @@ fail:
 void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
 {
 	down_write(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 
 	list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
 
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 }
 EXPORT_SYMBOL(mnt_set_expiry);
@@ -1935,7 +1936,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
 		return;
 
 	down_write(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 
 	/* extract from the expiration list every vfsmount that matches the
 	 * following criteria:
@@ -1954,7 +1955,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
 		touch_mnt_namespace(mnt->mnt_ns);
 		umount_tree(mnt, 1, &umounts);
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 
 	release_mounts(&umounts);
@@ -2218,9 +2219,9 @@ void mnt_make_shortterm(struct vfsmount *m)
 	struct mount *mnt = real_mount(m);
 	if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
 		return;
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	atomic_dec(&mnt->mnt_longterm);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 #endif
 }
 
@@ -2249,10 +2250,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
 		kfree(new_ns);
 		return ERR_PTR(-ENOMEM);
 	}
-	new_ns->root = new;
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	list_add_tail(&new_ns->list, &new->mnt_list);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 
 	/*
 	 * Second pass: switch the tsk->fs->* elements and mark new vfsmounts
@@ -2416,9 +2416,9 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
 int path_is_under(struct path *path1, struct path *path2)
 {
 	int res;
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 	return res;
 }
 EXPORT_SYMBOL(path_is_under);
@@ -2505,7 +2505,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	/* make sure we can reach put_old from new_root */
 	if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
 		goto out4;
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	detach_mnt(new_mnt, &parent_path);
 	detach_mnt(root_mnt, &root_parent);
 	/* mount old root on put_old */
@@ -2513,7 +2513,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	/* mount new_root on / */
 	attach_mnt(new_mnt, &root_parent);
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	chroot_fs_refs(&root, &new);
 	error = 0;
 out4:
@@ -2576,7 +2576,7 @@ void __init mnt_init(void)
 	for (u = 0; u < HASH_SIZE; u++)
 		INIT_LIST_HEAD(&mount_hashtable[u]);
 
-	br_lock_init(vfsmount_lock);
+	br_lock_init(&vfsmount_lock);
 
 	err = sysfs_init();
 	if (err)
@@ -2596,9 +2596,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
 	if (!atomic_dec_and_test(&ns->count))
 		return;
 	down_write(&namespace_sem);
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	umount_tree(ns->root, 0, &umount_list);
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	up_write(&namespace_sem);
 	release_mounts(&umount_list);
 	kfree(ns);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index fd9a872..32aa691 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -260,10 +260,10 @@ void nfs_readdir_clear_array(struct page *page)
 	struct nfs_cache_array *array;
 	int i;
 
-	array = kmap_atomic(page, KM_USER0);
+	array = kmap_atomic(page);
 	for (i = 0; i < array->size; i++)
 		kfree(array->array[i].string.name);
-	kunmap_atomic(array, KM_USER0);
+	kunmap_atomic(array);
 }
 
 /*
@@ -1870,11 +1870,11 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
 	if (!page)
 		return -ENOMEM;
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memcpy(kaddr, symname, pathlen);
 	if (pathlen < PAGE_SIZE)
 		memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
 	if (error != 0) {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f0c849c..3c58843 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -193,7 +193,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
 	 * when talking to the server, we always send cookie 0
 	 * instead of 1 or 2.
 	 */
-	start = p = kmap_atomic(*readdir->pages, KM_USER0);
+	start = p = kmap_atomic(*readdir->pages);
 	
 	if (cookie == 0) {
 		*p++ = xdr_one;                                  /* next */
@@ -221,7 +221,7 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
 
 	readdir->pgbase = (char *)p - (char *)start;
 	readdir->count -= readdir->pgbase;
-	kunmap_atomic(start, KM_USER0);
+	kunmap_atomic(start);
 }
 
 static int nfs4_wait_clnt_recover(struct nfs_client *clp)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index edf6d3e..2fc8c15 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -19,7 +19,6 @@
 #include <linux/fcntl.h>
 #include <linux/namei.h>
 #include <linux/delay.h>
-#include <linux/fsnotify.h>
 #include <linux/posix_acl_xattr.h>
 #include <linux/xattr.h>
 #include <linux/jhash.h>
@@ -933,7 +932,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 		nfsdstats.io_read += host_err;
 		*count = host_err;
 		err = 0;
-		fsnotify_access(file);
 	} else 
 		err = nfserrno(host_err);
 	return err;
@@ -1035,7 +1033,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 		goto out_nfserr;
 	*cnt = host_err;
 	nfsdstats.io_write += host_err;
-	fsnotify_modify(file);
 
 	/* clear setuid/setgid flag after write */
 	if (inode->i_mode & (S_ISUID | S_ISGID))
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index c9b342c..dab5c4c 100644
--- a/fs/nilfs2/cpfile.c
+++ b/fs/nilfs2/cpfile.c
@@ -218,11 +218,11 @@ int nilfs_cpfile_get_checkpoint(struct inode *cpfile,
 								 kaddr, 1);
 		mark_buffer_dirty(cp_bh);
 
-		kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(header_bh->b_page);
 		header = nilfs_cpfile_block_get_header(cpfile, header_bh,
 						       kaddr);
 		le64_add_cpu(&header->ch_ncheckpoints, 1);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		mark_buffer_dirty(header_bh);
 		nilfs_mdt_mark_dirty(cpfile);
 	}
@@ -313,7 +313,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
 			continue;
 		}
 
-		kaddr = kmap_atomic(cp_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(cp_bh->b_page);
 		cp = nilfs_cpfile_block_get_checkpoint(
 			cpfile, cno, cp_bh, kaddr);
 		nicps = 0;
@@ -334,7 +334,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
 						cpfile, cp_bh, kaddr, nicps);
 				if (count == 0) {
 					/* make hole */
-					kunmap_atomic(kaddr, KM_USER0);
+					kunmap_atomic(kaddr);
 					brelse(cp_bh);
 					ret =
 					  nilfs_cpfile_delete_checkpoint_block(
@@ -349,18 +349,18 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
 			}
 		}
 
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(cp_bh);
 	}
 
 	if (tnicps > 0) {
-		kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(header_bh->b_page);
 		header = nilfs_cpfile_block_get_header(cpfile, header_bh,
 						       kaddr);
 		le64_add_cpu(&header->ch_ncheckpoints, -(u64)tnicps);
 		mark_buffer_dirty(header_bh);
 		nilfs_mdt_mark_dirty(cpfile);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 
 	brelse(header_bh);
@@ -408,7 +408,7 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
 			continue; /* skip hole */
 		}
 
-		kaddr = kmap_atomic(bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(bh->b_page);
 		cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
 		for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) {
 			if (!nilfs_checkpoint_invalid(cp)) {
@@ -418,7 +418,7 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
 				n++;
 			}
 		}
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(bh);
 	}
 
@@ -451,10 +451,10 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
 		ret = nilfs_cpfile_get_header_block(cpfile, &bh);
 		if (ret < 0)
 			goto out;
-		kaddr = kmap_atomic(bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(bh->b_page);
 		header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr);
 		curr = le64_to_cpu(header->ch_snapshot_list.ssl_next);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(bh);
 		if (curr == 0) {
 			ret = 0;
@@ -472,7 +472,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
 			ret = 0; /* No snapshots (started from a hole block) */
 		goto out;
 	}
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	while (n < nci) {
 		cp = nilfs_cpfile_block_get_checkpoint(cpfile, curr, bh, kaddr);
 		curr = ~(__u64)0; /* Terminator */
@@ -488,7 +488,7 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
 
 		next_blkoff = nilfs_cpfile_get_blkoff(cpfile, next);
 		if (curr_blkoff != next_blkoff) {
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			brelse(bh);
 			ret = nilfs_cpfile_get_checkpoint_block(cpfile, next,
 								0, &bh);
@@ -496,12 +496,12 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
 				WARN_ON(ret == -ENOENT);
 				goto out;
 			}
-			kaddr = kmap_atomic(bh->b_page, KM_USER0);
+			kaddr = kmap_atomic(bh->b_page);
 		}
 		curr = next;
 		curr_blkoff = next_blkoff;
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(bh);
 	*cnop = curr;
 	ret = n;
@@ -592,24 +592,24 @@ static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno)
 	ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
 	if (ret < 0)
 		goto out_sem;
-	kaddr = kmap_atomic(cp_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(cp_bh->b_page);
 	cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
 	if (nilfs_checkpoint_invalid(cp)) {
 		ret = -ENOENT;
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		goto out_cp;
 	}
 	if (nilfs_checkpoint_snapshot(cp)) {
 		ret = 0;
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		goto out_cp;
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
 	if (ret < 0)
 		goto out_cp;
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
 	list = &header->ch_snapshot_list;
 	curr_bh = header_bh;
@@ -621,13 +621,13 @@ static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno)
 		prev_blkoff = nilfs_cpfile_get_blkoff(cpfile, prev);
 		curr = prev;
 		if (curr_blkoff != prev_blkoff) {
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			brelse(curr_bh);
 			ret = nilfs_cpfile_get_checkpoint_block(cpfile, curr,
 								0, &curr_bh);
 			if (ret < 0)
 				goto out_header;
-			kaddr = kmap_atomic(curr_bh->b_page, KM_USER0);
+			kaddr = kmap_atomic(curr_bh->b_page);
 		}
 		curr_blkoff = prev_blkoff;
 		cp = nilfs_cpfile_block_get_checkpoint(
@@ -635,7 +635,7 @@ static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno)
 		list = &cp->cp_snapshot_list;
 		prev = le64_to_cpu(list->ssl_prev);
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (prev != 0) {
 		ret = nilfs_cpfile_get_checkpoint_block(cpfile, prev, 0,
@@ -647,29 +647,29 @@ static int nilfs_cpfile_set_snapshot(struct inode *cpfile, __u64 cno)
 		get_bh(prev_bh);
 	}
 
-	kaddr = kmap_atomic(curr_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(curr_bh->b_page);
 	list = nilfs_cpfile_block_get_snapshot_list(
 		cpfile, curr, curr_bh, kaddr);
 	list->ssl_prev = cpu_to_le64(cno);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(cp_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(cp_bh->b_page);
 	cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
 	cp->cp_snapshot_list.ssl_next = cpu_to_le64(curr);
 	cp->cp_snapshot_list.ssl_prev = cpu_to_le64(prev);
 	nilfs_checkpoint_set_snapshot(cp);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(prev_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(prev_bh->b_page);
 	list = nilfs_cpfile_block_get_snapshot_list(
 		cpfile, prev, prev_bh, kaddr);
 	list->ssl_next = cpu_to_le64(cno);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
 	le64_add_cpu(&header->ch_nsnapshots, 1);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(prev_bh);
 	mark_buffer_dirty(curr_bh);
@@ -710,23 +710,23 @@ static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno)
 	ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
 	if (ret < 0)
 		goto out_sem;
-	kaddr = kmap_atomic(cp_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(cp_bh->b_page);
 	cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
 	if (nilfs_checkpoint_invalid(cp)) {
 		ret = -ENOENT;
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		goto out_cp;
 	}
 	if (!nilfs_checkpoint_snapshot(cp)) {
 		ret = 0;
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		goto out_cp;
 	}
 
 	list = &cp->cp_snapshot_list;
 	next = le64_to_cpu(list->ssl_next);
 	prev = le64_to_cpu(list->ssl_prev);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
 	if (ret < 0)
@@ -750,29 +750,29 @@ static int nilfs_cpfile_clear_snapshot(struct inode *cpfile, __u64 cno)
 		get_bh(prev_bh);
 	}
 
-	kaddr = kmap_atomic(next_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(next_bh->b_page);
 	list = nilfs_cpfile_block_get_snapshot_list(
 		cpfile, next, next_bh, kaddr);
 	list->ssl_prev = cpu_to_le64(prev);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(prev_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(prev_bh->b_page);
 	list = nilfs_cpfile_block_get_snapshot_list(
 		cpfile, prev, prev_bh, kaddr);
 	list->ssl_next = cpu_to_le64(next);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(cp_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(cp_bh->b_page);
 	cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, cp_bh, kaddr);
 	cp->cp_snapshot_list.ssl_next = cpu_to_le64(0);
 	cp->cp_snapshot_list.ssl_prev = cpu_to_le64(0);
 	nilfs_checkpoint_clear_snapshot(cp);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = nilfs_cpfile_block_get_header(cpfile, header_bh, kaddr);
 	le64_add_cpu(&header->ch_nsnapshots, -1);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(next_bh);
 	mark_buffer_dirty(prev_bh);
@@ -829,13 +829,13 @@ int nilfs_cpfile_is_snapshot(struct inode *cpfile, __u64 cno)
 	ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &bh);
 	if (ret < 0)
 		goto out;
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
 	if (nilfs_checkpoint_invalid(cp))
 		ret = -ENOENT;
 	else
 		ret = nilfs_checkpoint_snapshot(cp);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(bh);
 
  out:
@@ -912,12 +912,12 @@ int nilfs_cpfile_get_stat(struct inode *cpfile, struct nilfs_cpstat *cpstat)
 	ret = nilfs_cpfile_get_header_block(cpfile, &bh);
 	if (ret < 0)
 		goto out_sem;
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	header = nilfs_cpfile_block_get_header(cpfile, bh, kaddr);
 	cpstat->cs_cno = nilfs_mdt_cno(cpfile);
 	cpstat->cs_ncps = le64_to_cpu(header->ch_ncheckpoints);
 	cpstat->cs_nsss = le64_to_cpu(header->ch_nsnapshots);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(bh);
 
  out_sem:
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index fcc2f86..b5c13f3 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -85,13 +85,13 @@ void nilfs_dat_commit_alloc(struct inode *dat, struct nilfs_palloc_req *req)
 	struct nilfs_dat_entry *entry;
 	void *kaddr;
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
 	entry->de_end = cpu_to_le64(NILFS_CNO_MAX);
 	entry->de_blocknr = cpu_to_le64(0);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nilfs_palloc_commit_alloc_entry(dat, req);
 	nilfs_dat_commit_entry(dat, req);
@@ -109,13 +109,13 @@ static void nilfs_dat_commit_free(struct inode *dat,
 	struct nilfs_dat_entry *entry;
 	void *kaddr;
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	entry->de_start = cpu_to_le64(NILFS_CNO_MIN);
 	entry->de_end = cpu_to_le64(NILFS_CNO_MIN);
 	entry->de_blocknr = cpu_to_le64(0);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nilfs_dat_commit_entry(dat, req);
 	nilfs_palloc_commit_free_entry(dat, req);
@@ -136,12 +136,12 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
 	struct nilfs_dat_entry *entry;
 	void *kaddr;
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
 	entry->de_blocknr = cpu_to_le64(blocknr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nilfs_dat_commit_entry(dat, req);
 }
@@ -160,12 +160,12 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)
 		return ret;
 	}
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	start = le64_to_cpu(entry->de_start);
 	blocknr = le64_to_cpu(entry->de_blocknr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (blocknr == 0) {
 		ret = nilfs_palloc_prepare_free_entry(dat, req);
@@ -186,7 +186,7 @@ void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
 	sector_t blocknr;
 	void *kaddr;
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	end = start = le64_to_cpu(entry->de_start);
@@ -196,7 +196,7 @@ void nilfs_dat_commit_end(struct inode *dat, struct nilfs_palloc_req *req,
 	}
 	entry->de_end = cpu_to_le64(end);
 	blocknr = le64_to_cpu(entry->de_blocknr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (blocknr == 0)
 		nilfs_dat_commit_free(dat, req);
@@ -211,12 +211,12 @@ void nilfs_dat_abort_end(struct inode *dat, struct nilfs_palloc_req *req)
 	sector_t blocknr;
 	void *kaddr;
 
-	kaddr = kmap_atomic(req->pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req->pr_entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
 					     req->pr_entry_bh, kaddr);
 	start = le64_to_cpu(entry->de_start);
 	blocknr = le64_to_cpu(entry->de_blocknr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (start == nilfs_mdt_cno(dat) && blocknr == 0)
 		nilfs_palloc_abort_free_entry(dat, req);
@@ -346,20 +346,20 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr)
 		}
 	}
 
-	kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 	if (unlikely(entry->de_blocknr == cpu_to_le64(0))) {
 		printk(KERN_CRIT "%s: vbn = %llu, [%llu, %llu)\n", __func__,
 		       (unsigned long long)vblocknr,
 		       (unsigned long long)le64_to_cpu(entry->de_start),
 		       (unsigned long long)le64_to_cpu(entry->de_end));
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(entry_bh);
 		return -EINVAL;
 	}
 	WARN_ON(blocknr == 0);
 	entry->de_blocknr = cpu_to_le64(blocknr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(entry_bh);
 	nilfs_mdt_mark_dirty(dat);
@@ -409,7 +409,7 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 		}
 	}
 
-	kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(entry_bh->b_page);
 	entry = nilfs_palloc_block_get_entry(dat, vblocknr, entry_bh, kaddr);
 	blocknr = le64_to_cpu(entry->de_blocknr);
 	if (blocknr == 0) {
@@ -419,7 +419,7 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
 	*blocknrp = blocknr;
 
  out:
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(entry_bh);
 	return ret;
 }
@@ -440,7 +440,7 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
 						   0, &entry_bh);
 		if (ret < 0)
 			return ret;
-		kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(entry_bh->b_page);
 		/* last virtual block number in this block */
 		first = vinfo->vi_vblocknr;
 		do_div(first, entries_per_block);
@@ -456,7 +456,7 @@ ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
 			vinfo->vi_end = le64_to_cpu(entry->de_end);
 			vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
 		}
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(entry_bh);
 	}
 
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index ca35b3a..df1a7fb 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -602,7 +602,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
 		unlock_page(page);
 		goto fail;
 	}
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memset(kaddr, 0, chunk_size);
 	de = (struct nilfs_dir_entry *)kaddr;
 	de->name_len = 1;
@@ -617,7 +617,7 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent)
 	de->inode = cpu_to_le64(parent->i_ino);
 	memcpy(de->name, "..\0", 4);
 	nilfs_set_de_type(de, inode);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	nilfs_commit_chunk(page, mapping, 0, chunk_size);
 fail:
 	page_cache_release(page);
diff --git a/fs/nilfs2/ifile.c b/fs/nilfs2/ifile.c
index 684d763..5a48df7 100644
--- a/fs/nilfs2/ifile.c
+++ b/fs/nilfs2/ifile.c
@@ -122,11 +122,11 @@ int nilfs_ifile_delete_inode(struct inode *ifile, ino_t ino)
 		return ret;
 	}
 
-	kaddr = kmap_atomic(req.pr_entry_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(req.pr_entry_bh->b_page);
 	raw_inode = nilfs_palloc_block_get_entry(ifile, req.pr_entry_nr,
 						 req.pr_entry_bh, kaddr);
 	raw_inode->i_flags = 0;
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(req.pr_entry_bh);
 	brelse(req.pr_entry_bh);
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index 800e8d7..f9897d0 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -58,12 +58,12 @@ nilfs_mdt_insert_new_block(struct inode *inode, unsigned long block,
 
 	set_buffer_mapped(bh);
 
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	memset(kaddr + bh_offset(bh), 0, 1 << inode->i_blkbits);
 	if (init_block)
 		init_block(inode, bh, kaddr);
 	flush_dcache_page(bh->b_page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	set_buffer_uptodate(bh);
 	mark_buffer_dirty(bh);
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
index 65221a0..3e7b2a0 100644
--- a/fs/nilfs2/page.c
+++ b/fs/nilfs2/page.c
@@ -119,11 +119,11 @@ void nilfs_copy_buffer(struct buffer_head *dbh, struct buffer_head *sbh)
 	struct page *spage = sbh->b_page, *dpage = dbh->b_page;
 	struct buffer_head *bh;
 
-	kaddr0 = kmap_atomic(spage, KM_USER0);
-	kaddr1 = kmap_atomic(dpage, KM_USER1);
+	kaddr0 = kmap_atomic(spage);
+	kaddr1 = kmap_atomic(dpage);
 	memcpy(kaddr1 + bh_offset(dbh), kaddr0 + bh_offset(sbh), sbh->b_size);
-	kunmap_atomic(kaddr1, KM_USER1);
-	kunmap_atomic(kaddr0, KM_USER0);
+	kunmap_atomic(kaddr1);
+	kunmap_atomic(kaddr0);
 
 	dbh->b_state = sbh->b_state & NILFS_BUFFER_INHERENT_BITS;
 	dbh->b_blocknr = sbh->b_blocknr;
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index a604ac0..f1626f5 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -493,9 +493,9 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
 	if (unlikely(!bh_org))
 		return -EIO;
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(bh_org);
 	return 0;
 }
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 850a7c0..dc9a913 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -227,9 +227,9 @@ static void nilfs_segbuf_fill_in_data_crc(struct nilfs_segment_buffer *segbuf,
 		crc = crc32_le(crc, bh->b_data, bh->b_size);
 	}
 	list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) {
-		kaddr = kmap_atomic(bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(bh->b_page);
 		crc = crc32_le(crc, kaddr + bh_offset(bh), bh->b_size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 	raw_sum->ss_datasum = cpu_to_le32(crc);
 }
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 0a0aba6..c5b7653 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -111,11 +111,11 @@ static void nilfs_sufile_mod_counter(struct buffer_head *header_bh,
 	struct nilfs_sufile_header *header;
 	void *kaddr;
 
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = kaddr + bh_offset(header_bh);
 	le64_add_cpu(&header->sh_ncleansegs, ncleanadd);
 	le64_add_cpu(&header->sh_ndirtysegs, ndirtyadd);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(header_bh);
 }
@@ -319,11 +319,11 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
 	ret = nilfs_sufile_get_header_block(sufile, &header_bh);
 	if (ret < 0)
 		goto out_sem;
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = kaddr + bh_offset(header_bh);
 	ncleansegs = le64_to_cpu(header->sh_ncleansegs);
 	last_alloc = le64_to_cpu(header->sh_last_alloc);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nsegments = nilfs_sufile_get_nsegments(sufile);
 	maxsegnum = sui->allocmax;
@@ -356,7 +356,7 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
 							   &su_bh);
 		if (ret < 0)
 			goto out_header;
-		kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(su_bh->b_page);
 		su = nilfs_sufile_block_get_segment_usage(
 			sufile, segnum, su_bh, kaddr);
 
@@ -367,14 +367,14 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
 				continue;
 			/* found a clean segment */
 			nilfs_segment_usage_set_dirty(su);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 
-			kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+			kaddr = kmap_atomic(header_bh->b_page);
 			header = kaddr + bh_offset(header_bh);
 			le64_add_cpu(&header->sh_ncleansegs, -1);
 			le64_add_cpu(&header->sh_ndirtysegs, 1);
 			header->sh_last_alloc = cpu_to_le64(segnum);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 
 			sui->ncleansegs--;
 			mark_buffer_dirty(header_bh);
@@ -385,7 +385,7 @@ int nilfs_sufile_alloc(struct inode *sufile, __u64 *segnump)
 			goto out_header;
 		}
 
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(su_bh);
 	}
 
@@ -407,16 +407,16 @@ void nilfs_sufile_do_cancel_free(struct inode *sufile, __u64 segnum,
 	struct nilfs_segment_usage *su;
 	void *kaddr;
 
-	kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(su_bh->b_page);
 	su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
 	if (unlikely(!nilfs_segment_usage_clean(su))) {
 		printk(KERN_WARNING "%s: segment %llu must be clean\n",
 		       __func__, (unsigned long long)segnum);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		return;
 	}
 	nilfs_segment_usage_set_dirty(su);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nilfs_sufile_mod_counter(header_bh, -1, 1);
 	NILFS_SUI(sufile)->ncleansegs--;
@@ -433,11 +433,11 @@ void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum,
 	void *kaddr;
 	int clean, dirty;
 
-	kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(su_bh->b_page);
 	su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
 	if (su->su_flags == cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY) &&
 	    su->su_nblocks == cpu_to_le32(0)) {
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		return;
 	}
 	clean = nilfs_segment_usage_clean(su);
@@ -447,7 +447,7 @@ void nilfs_sufile_do_scrap(struct inode *sufile, __u64 segnum,
 	su->su_lastmod = cpu_to_le64(0);
 	su->su_nblocks = cpu_to_le32(0);
 	su->su_flags = cpu_to_le32(1UL << NILFS_SEGMENT_USAGE_DIRTY);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	nilfs_sufile_mod_counter(header_bh, clean ? (u64)-1 : 0, dirty ? 0 : 1);
 	NILFS_SUI(sufile)->ncleansegs -= clean;
@@ -464,12 +464,12 @@ void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum,
 	void *kaddr;
 	int sudirty;
 
-	kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(su_bh->b_page);
 	su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
 	if (nilfs_segment_usage_clean(su)) {
 		printk(KERN_WARNING "%s: segment %llu is already clean\n",
 		       __func__, (unsigned long long)segnum);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		return;
 	}
 	WARN_ON(nilfs_segment_usage_error(su));
@@ -477,7 +477,7 @@ void nilfs_sufile_do_free(struct inode *sufile, __u64 segnum,
 
 	sudirty = nilfs_segment_usage_dirty(su);
 	nilfs_segment_usage_set_clean(su);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	mark_buffer_dirty(su_bh);
 
 	nilfs_sufile_mod_counter(header_bh, 1, sudirty ? (u64)-1 : 0);
@@ -525,13 +525,13 @@ int nilfs_sufile_set_segment_usage(struct inode *sufile, __u64 segnum,
 	if (ret < 0)
 		goto out_sem;
 
-	kaddr = kmap_atomic(bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(bh->b_page);
 	su = nilfs_sufile_block_get_segment_usage(sufile, segnum, bh, kaddr);
 	WARN_ON(nilfs_segment_usage_error(su));
 	if (modtime)
 		su->su_lastmod = cpu_to_le64(modtime);
 	su->su_nblocks = cpu_to_le32(nblocks);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(bh);
 	nilfs_mdt_mark_dirty(sufile);
@@ -572,7 +572,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
 	if (ret < 0)
 		goto out_sem;
 
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = kaddr + bh_offset(header_bh);
 	sustat->ss_nsegs = nilfs_sufile_get_nsegments(sufile);
 	sustat->ss_ncleansegs = le64_to_cpu(header->sh_ncleansegs);
@@ -582,7 +582,7 @@ int nilfs_sufile_get_stat(struct inode *sufile, struct nilfs_sustat *sustat)
 	spin_lock(&nilfs->ns_last_segment_lock);
 	sustat->ss_prot_seq = nilfs->ns_prot_seq;
 	spin_unlock(&nilfs->ns_last_segment_lock);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(header_bh);
 
  out_sem:
@@ -598,15 +598,15 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
 	void *kaddr;
 	int suclean;
 
-	kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(su_bh->b_page);
 	su = nilfs_sufile_block_get_segment_usage(sufile, segnum, su_bh, kaddr);
 	if (nilfs_segment_usage_error(su)) {
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		return;
 	}
 	suclean = nilfs_segment_usage_clean(su);
 	nilfs_segment_usage_set_error(su);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (suclean) {
 		nilfs_sufile_mod_counter(header_bh, -1, 0);
@@ -675,7 +675,7 @@ static int nilfs_sufile_truncate_range(struct inode *sufile,
 			/* hole */
 			continue;
 		}
-		kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(su_bh->b_page);
 		su = nilfs_sufile_block_get_segment_usage(
 			sufile, segnum, su_bh, kaddr);
 		su2 = su;
@@ -684,7 +684,7 @@ static int nilfs_sufile_truncate_range(struct inode *sufile,
 			     ~(1UL << NILFS_SEGMENT_USAGE_ERROR)) ||
 			    nilfs_segment_is_active(nilfs, segnum + j)) {
 				ret = -EBUSY;
-				kunmap_atomic(kaddr, KM_USER0);
+				kunmap_atomic(kaddr);
 				brelse(su_bh);
 				goto out_header;
 			}
@@ -696,7 +696,7 @@ static int nilfs_sufile_truncate_range(struct inode *sufile,
 				nc++;
 			}
 		}
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		if (nc > 0) {
 			mark_buffer_dirty(su_bh);
 			ncleaned += nc;
@@ -772,10 +772,10 @@ int nilfs_sufile_resize(struct inode *sufile, __u64 newnsegs)
 		sui->ncleansegs -= nsegs - newnsegs;
 	}
 
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = kaddr + bh_offset(header_bh);
 	header->sh_ncleansegs = cpu_to_le64(sui->ncleansegs);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	mark_buffer_dirty(header_bh);
 	nilfs_mdt_mark_dirty(sufile);
@@ -840,7 +840,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 			continue;
 		}
 
-		kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
+		kaddr = kmap_atomic(su_bh->b_page);
 		su = nilfs_sufile_block_get_segment_usage(
 			sufile, segnum, su_bh, kaddr);
 		for (j = 0; j < n;
@@ -853,7 +853,7 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
 				si->sui_flags |=
 					(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
 		}
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		brelse(su_bh);
 	}
 	ret = nsegs;
@@ -902,10 +902,10 @@ int nilfs_sufile_read(struct super_block *sb, size_t susize,
 		goto failed;
 
 	sui = NILFS_SUI(sufile);
-	kaddr = kmap_atomic(header_bh->b_page, KM_USER0);
+	kaddr = kmap_atomic(header_bh->b_page);
 	header = kaddr + bh_offset(header_bh);
 	sui->ncleansegs = le64_to_cpu(header->sh_ncleansegs);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	brelse(header_bh);
 
 	sui->allocmax = nilfs_sufile_get_nsegments(sufile) - 1;
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 3344bdd..89ec7e0 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -31,7 +31,6 @@ int dir_notify_enable __read_mostly = 1;
 static struct kmem_cache *dnotify_struct_cache __read_mostly;
 static struct kmem_cache *dnotify_mark_cache __read_mostly;
 static struct fsnotify_group *dnotify_group __read_mostly;
-static DEFINE_MUTEX(dnotify_mark_mutex);
 
 /*
  * dnotify will attach one of these to each inode (i_fsnotify_marks) which
@@ -183,7 +182,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
 		return;
 	dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
 
-	mutex_lock(&dnotify_mark_mutex);
+	mutex_lock(&dnotify_group->mutex);
 
 	spin_lock(&fsn_mark->lock);
 	prev = &dn_mark->dn;
@@ -199,11 +198,11 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
 
 	spin_unlock(&fsn_mark->lock);
 
-	/* nothing else could have found us thanks to the dnotify_mark_mutex */
+	/* nothing else could have found us thanks to the dnotify_group mutex */
 	if (dn_mark->dn == NULL)
 		fsnotify_destroy_mark(fsn_mark);
 
-	mutex_unlock(&dnotify_mark_mutex);
+	mutex_unlock(&dnotify_group->mutex);
 
 	fsnotify_put_mark(fsn_mark);
 }
@@ -326,7 +325,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
 	new_dn_mark->dn = NULL;
 
 	/* this is needed to prevent the fcntl/close race described below */
-	mutex_lock(&dnotify_mark_mutex);
+	mutex_lock(&dnotify_group->mutex);
 
 	/* add the new_fsn_mark or find an old one. */
 	fsn_mark = fsnotify_find_inode_mark(dnotify_group, inode);
@@ -348,8 +347,8 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
 
 	/* if (f != filp) means that we lost a race and another task/thread
 	 * actually closed the fd we are still playing with before we grabbed
-	 * the dnotify_mark_mutex and fsn_mark->lock.  Since closing the fd is the
-	 * only time we clean up the marks we need to get our mark off
+	 * the dnotify_group mutex and fsn_mark->lock. Since closing the fd is
+	 * the only time we clean up the marks we need to get our mark off
 	 * the list. */
 	if (f != filp) {
 		/* if we added ourselves, shoot ourselves, it's possible that
@@ -387,7 +386,7 @@ out:
 	if (destroy)
 		fsnotify_destroy_mark(fsn_mark);
 
-	mutex_unlock(&dnotify_mark_mutex);
+	mutex_unlock(&dnotify_group->mutex);
 	fsnotify_put_mark(fsn_mark);
 out_err:
 	if (new_fsn_mark)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index f35794b..c2ba86a 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -184,13 +184,6 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
 		marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
 		marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
 	} else if (inode_mark) {
-		/*
-		 * if the event is for a child and this inode doesn't care about
-		 * events on the child, don't send it!
-		 */
-		if ((event_mask & FS_EVENT_ON_CHILD) &&
-		    !(inode_mark->mask & FS_EVENT_ON_CHILD))
-			return false;
 		marks_mask = inode_mark->mask;
 		marks_ignored_mask = inode_mark->ignored_mask;
 	} else if (vfsmnt_mark) {
@@ -204,10 +197,21 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
 	    (marks_ignored_mask & FS_ISDIR))
 		return false;
 
-	if (event_mask & marks_mask & ~marks_ignored_mask)
-		return true;
+	/*
+	 * if the event is for a child and this inode doesn't care about
+	 * events on the child, don't send it!
+	 */
+	if ((event_mask & FS_EVENT_ON_CHILD) &&
+	    !(marks_mask & FS_EVENT_ON_CHILD))
+		return false;
 
-	return false;
+	/*
+	 * It might seem logical to check:
+	 * if (event_mask & marks_mask & ~marks_ignored_mask)
+	 * 	return true;
+	 * but we we know this was true from the caller so just return true.
+	 */
+	return true;
 }
 
 static void fanotify_free_group_priv(struct fsnotify_group *group)
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 3568c8a..d688731 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -64,6 +64,7 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
 	struct dentry *dentry;
 	struct vfsmount *mnt;
 	struct file *new_file;
+	unsigned int flags;
 
 	pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
@@ -85,12 +86,22 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
 	mnt = mntget(event->path.mnt);
 	/* it's possible this event was an overflow event.  in that case dentry and mnt
 	 * are NULL;  That's fine, just don't call dentry open */
-	if (dentry && mnt)
-		new_file = dentry_open(dentry, mnt,
-				       group->fanotify_data.f_flags | FMODE_NONOTIFY,
-				       current_cred());
-	else
+	if (dentry && mnt) {
+		flags = group->fanotify_data.f_flags;
+		new_file = dentry_open(dentry, mnt, flags, current_cred());
+		/*
+		 * Attempt fallback to read-only access if writable was not possible
+		 * in order to at least provide something to the listener.
+		 */
+		if (IS_ERR(new_file) && group->fanotify_data.readonly_fallback) {
+			flags &= ~O_ACCMODE;
+			flags |= O_RDONLY;
+			new_file = dentry_open(dentry, mnt, flags,
+					       current_cred());
+		}
+	} else {
 		new_file = ERR_PTR(-EOVERFLOW);
+	}
 	if (IS_ERR(new_file)) {
 		/*
 		 * we still send an event even if we can't open the file.  this
@@ -210,14 +221,6 @@ static int prepare_for_access_response(struct fsnotify_group *group,
 	re->fd = fd;
 
 	mutex_lock(&group->fanotify_data.access_mutex);
-
-	if (atomic_read(&group->fanotify_data.bypass_perm)) {
-		mutex_unlock(&group->fanotify_data.access_mutex);
-		kmem_cache_free(fanotify_response_event_cache, re);
-		event->response = FAN_ALLOW;
-		return 0;
-	}
-		
 	list_add_tail(&re->list, &group->fanotify_data.access_list);
 	mutex_unlock(&group->fanotify_data.access_mutex);
 
@@ -518,6 +521,7 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
 					    unsigned int flags)
 {
 	__u32 oldmask;
+	int destroy_mark;
 
 	spin_lock(&fsn_mark->lock);
 	if (!(flags & FAN_MARK_IGNORED_MASK)) {
@@ -527,9 +531,10 @@ static __u32 fanotify_mark_remove_from_mask(struct fsnotify_mark *fsn_mark,
 		oldmask = fsn_mark->ignored_mask;
 		fsnotify_set_mark_ignored_mask_locked(fsn_mark, (oldmask & ~mask));
 	}
+	destroy_mark = (!fsn_mark->mask && !fsn_mark->ignored_mask);
 	spin_unlock(&fsn_mark->lock);
 
-	if (!(oldmask & ~mask))
+	if (destroy_mark)
 		fsnotify_destroy_mark(fsn_mark);
 
 	return mask & oldmask;
@@ -541,17 +546,23 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark = NULL;
 	__u32 removed;
+	int ret;
 
+	mutex_lock(&group->mutex);
+	ret = -ENOENT;
 	fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
 	if (!fsn_mark)
-		return -ENOENT;
+		goto err;
 
 	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
 	fsnotify_put_mark(fsn_mark);
 	if (removed & real_mount(mnt)->mnt_fsnotify_mask)
 		fsnotify_recalc_vfsmount_mask(mnt);
+	ret = 0;
+err:
+	mutex_unlock(&group->mutex);
 
-	return 0;
+	return ret;
 }
 
 static int fanotify_remove_inode_mark(struct fsnotify_group *group,
@@ -560,18 +571,24 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark = NULL;
 	__u32 removed;
+	int ret;
 
+	mutex_lock(&group->mutex);
+	ret = -ENOENT;
 	fsn_mark = fsnotify_find_inode_mark(group, inode);
 	if (!fsn_mark)
-		return -ENOENT;
+		goto err;
 
 	removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags);
 	/* matches the fsnotify_find_inode_mark() */
 	fsnotify_put_mark(fsn_mark);
 	if (removed & inode->i_fsnotify_mask)
 		fsnotify_recalc_inode_mask(inode);
+	ret = 0;
+err:
+	mutex_unlock(&group->mutex);
 
-	return 0;
+	return ret;
 }
 
 static __u32 fanotify_mark_add_to_mask(struct fsnotify_mark *fsn_mark,
@@ -607,28 +624,35 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark;
 	__u32 added;
-	int ret = 0;
+	int ret;
 
+	mutex_lock(&group->mutex);
 	fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
 	if (!fsn_mark) {
-		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
-			return -ENOSPC;
+		ret = -ENOSPC;
+		if (atomic_read(&group->num_marks) >
+		    group->fanotify_data.max_marks)
+			goto err;
 
+		ret = -ENOMEM;
 		fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
 		if (!fsn_mark)
-			return -ENOMEM;
+			goto err;
 
 		fsnotify_init_mark(fsn_mark, fanotify_free_mark);
 		ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0);
 		if (ret)
-			goto err;
+			goto err2;
 	}
 	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
 
 	if (added & ~real_mount(mnt)->mnt_fsnotify_mask)
 		fsnotify_recalc_vfsmount_mask(mnt);
-err:
+	ret = 0;
+err2:
 	fsnotify_put_mark(fsn_mark);
+err:
+	mutex_unlock(&group->mutex);
 	return ret;
 }
 
@@ -638,7 +662,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 {
 	struct fsnotify_mark *fsn_mark;
 	__u32 added;
-	int ret = 0;
+	int ret;
 
 	pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -652,26 +676,33 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 	    (atomic_read(&inode->i_writecount) > 0))
 		return 0;
 
+	mutex_lock(&group->mutex);
 	fsn_mark = fsnotify_find_inode_mark(group, inode);
 	if (!fsn_mark) {
-		if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
-			return -ENOSPC;
+		ret = -ENOSPC;
+		if (atomic_read(&group->num_marks) >
+		    group->fanotify_data.max_marks)
+			goto err;
 
+		ret = -ENOMEM;
 		fsn_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
 		if (!fsn_mark)
-			return -ENOMEM;
+			goto err;
 
 		fsnotify_init_mark(fsn_mark, fanotify_free_mark);
 		ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0);
 		if (ret)
-			goto err;
+			goto err2;
 	}
 	added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
 
 	if (added & ~inode->i_fsnotify_mask)
 		fsnotify_recalc_inode_mask(inode);
-err:
+	ret = 0;
+err2:
 	fsnotify_put_mark(fsn_mark);
+err:
+	mutex_unlock(&group->mutex);
 	return ret;
 }
 
@@ -713,7 +744,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 	group->fanotify_data.user = user;
 	atomic_inc(&user->fanotify_listeners);
 
-	group->fanotify_data.f_flags = event_f_flags;
+	group->fanotify_data.f_flags = event_f_flags | FMODE_NONOTIFY;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
 	mutex_init(&group->fanotify_data.access_mutex);
 	init_waitqueue_head(&group->fanotify_data.access_waitq);
@@ -753,6 +784,14 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 		group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS;
 	}
 
+	fd = -EINVAL;
+	if (flags & FAN_READONLY_FALLBACK) {
+		if ((event_f_flags & O_ACCMODE) == O_RDWR)
+			group->fanotify_data.readonly_fallback = true;
+		else
+			goto out_put_group;
+	}
+
 	fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags);
 	if (fd < 0)
 		goto out_put_group;
diff --git a/fs/notify/group.c b/fs/notify/group.c
index 63fc294..7558c54 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -90,6 +90,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
 	 */
 	atomic_set(&group->num_marks, 1);
 
+	mutex_init(&group->mutex);
 	mutex_init(&group->notification_mutex);
 	INIT_LIST_HEAD(&group->notification_list);
 	init_waitqueue_head(&group->notification_waitq);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index f104d56..b79dac8 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -102,17 +102,6 @@ static DEFINE_SPINLOCK(destroy_lock);
 static LIST_HEAD(destroy_list);
 static DECLARE_WAIT_QUEUE_HEAD(destroy_waitq);
 
-void fsnotify_get_mark(struct fsnotify_mark *mark)
-{
-	atomic_inc(&mark->refcnt);
-}
-
-void fsnotify_put_mark(struct fsnotify_mark *mark)
-{
-	if (atomic_dec_and_test(&mark->refcnt))
-		mark->free_mark(mark);
-}
-
 /*
  * Any time a mark is getting freed we end up here.
  * The caller had better be holding a reference to this mark so we don't actually
@@ -218,7 +207,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 		      struct fsnotify_group *group, struct inode *inode,
 		      struct vfsmount *mnt, int allow_dups)
 {
-	int ret = 0;
+	int ret;
 
 	BUG_ON(inode && mnt);
 	BUG_ON(!inode && !mnt);
@@ -233,23 +222,20 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 	spin_lock(&group->mark_lock);
 
 	mark->flags |= FSNOTIFY_MARK_FLAG_ALIVE;
-
 	mark->group = group;
 	list_add(&mark->g_list, &group->marks_list);
-	atomic_inc(&group->num_marks);
 	fsnotify_get_mark(mark); /* for i_list and g_list */
+	atomic_inc(&group->num_marks);
 
-	if (inode) {
+	ret = 0;
+	if (inode)
 		ret = fsnotify_add_inode_mark(mark, group, inode, allow_dups);
-		if (ret)
-			goto err;
-	} else if (mnt) {
+	else if (mnt)
 		ret = fsnotify_add_vfsmount_mark(mark, group, mnt, allow_dups);
-		if (ret)
-			goto err;
-	} else {
+	else
 		BUG();
-	}
+	if (ret)
+		goto err;
 
 	spin_unlock(&group->mark_lock);
 
@@ -261,7 +247,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark,
 	if (inode)
 		__fsnotify_update_child_dentry_flags(inode);
 
-	return ret;
+	return 0;
 err:
 	mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
 	list_del_init(&mark->g_list);
@@ -347,6 +333,10 @@ static int fsnotify_mark_destroy(void *ignored)
 
 		synchronize_srcu(&fsnotify_mark_srcu);
 
+		/*
+		 * at this point we cannot be found via the i_list or g_list so
+		 * drop that reference.
+		 */
 		list_for_each_entry_safe(mark, next, &private_destroy_list, destroy_list) {
 			list_del_init(&mark->destroy_list);
 			fsnotify_put_mark(mark);
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 0b1e885b..fa9c05f 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -94,11 +94,11 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
 			if (file_ofs < init_size)
 				ofs = init_size - file_ofs;
 			local_irq_save(flags);
-			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+			kaddr = kmap_atomic(page);
 			memset(kaddr + bh_offset(bh) + ofs, 0,
 					bh->b_size - ofs);
 			flush_dcache_page(page);
-			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+			kunmap_atomic(kaddr);
 			local_irq_restore(flags);
 		}
 	} else {
@@ -147,11 +147,11 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
 		/* Should have been verified before we got here... */
 		BUG_ON(!recs);
 		local_irq_save(flags);
-		kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
+		kaddr = kmap_atomic(page);
 		for (i = 0; i < recs; i++)
 			post_read_mst_fixup((NTFS_RECORD*)(kaddr +
 					i * rec_size), rec_size);
-		kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+		kunmap_atomic(kaddr);
 		local_irq_restore(flags);
 		flush_dcache_page(page);
 		if (likely(page_uptodate && !PageError(page)))
@@ -504,7 +504,7 @@ retry_readpage:
 		/* Race with shrinking truncate. */
 		attr_len = i_size;
 	}
-	addr = kmap_atomic(page, KM_USER0);
+	addr = kmap_atomic(page);
 	/* Copy the data to the page. */
 	memcpy(addr, (u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset),
@@ -512,7 +512,7 @@ retry_readpage:
 	/* Zero the remainder of the page. */
 	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
 	flush_dcache_page(page);
-	kunmap_atomic(addr, KM_USER0);
+	kunmap_atomic(addr);
 put_unm_err_out:
 	ntfs_attr_put_search_ctx(ctx);
 unm_err_out:
@@ -746,14 +746,14 @@ lock_retry_remap:
 			unsigned long *bpos, *bend;
 
 			/* Check if the buffer is zero. */
-			kaddr = kmap_atomic(page, KM_USER0);
+			kaddr = kmap_atomic(page);
 			bpos = (unsigned long *)(kaddr + bh_offset(bh));
 			bend = (unsigned long *)((u8*)bpos + blocksize);
 			do {
 				if (unlikely(*bpos))
 					break;
 			} while (likely(++bpos < bend));
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			if (bpos == bend) {
 				/*
 				 * Buffer is zero and sparse, no need to write
@@ -1495,14 +1495,14 @@ retry_writepage:
 		/* Shrinking cannot fail. */
 		BUG_ON(err);
 	}
-	addr = kmap_atomic(page, KM_USER0);
+	addr = kmap_atomic(page);
 	/* Copy the data from the page to the mft record. */
 	memcpy((u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset),
 			addr, attr_len);
 	/* Zero out of bounds area in the page cache page. */
 	memset(addr + attr_len, 0, PAGE_CACHE_SIZE - attr_len);
-	kunmap_atomic(addr, KM_USER0);
+	kunmap_atomic(addr);
 	flush_dcache_page(page);
 	flush_dcache_mft_record_page(ctx->ntfs_ino);
 	/* We are done with the page. */
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index f14fde2..08c9bcd 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -1656,12 +1656,12 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
 	attr_size = le32_to_cpu(a->data.resident.value_length);
 	BUG_ON(attr_size != data_size);
 	if (page && !PageUptodate(page)) {
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memcpy(kaddr, (u8*)a +
 				le16_to_cpu(a->data.resident.value_offset),
 				attr_size);
 		memset(kaddr + attr_size, 0, PAGE_CACHE_SIZE - attr_size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		flush_dcache_page(page);
 		SetPageUptodate(page);
 	}
@@ -1806,9 +1806,9 @@ undo_err_out:
 			sizeof(a->data.resident.reserved));
 	/* Copy the data from the page back to the attribute value. */
 	if (page) {
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memcpy((u8*)a + mp_ofs, kaddr, attr_size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 	/* Setup the allocated size in the ntfs inode in case it changed. */
 	write_lock_irqsave(&ni->size_lock, flags);
@@ -2540,10 +2540,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
 		size = PAGE_CACHE_SIZE;
 		if (idx == end)
 			size = end_ofs;
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memset(kaddr + start_ofs, val, size - start_ofs);
 		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		set_page_dirty(page);
 		page_cache_release(page);
 		balance_dirty_pages_ratelimited(mapping);
@@ -2561,10 +2561,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
 					"page (index 0x%lx).", idx);
 			return -ENOMEM;
 		}
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memset(kaddr, val, PAGE_CACHE_SIZE);
 		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		/*
 		 * If the page has buffers, mark them uptodate since buffer
 		 * state and not page state is definitive in 2.6 kernels.
@@ -2598,10 +2598,10 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
 					"(error, index 0x%lx).", idx);
 			return PTR_ERR(page);
 		}
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memset(kaddr, val, end_ofs);
 		flush_dcache_page(page);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		set_page_dirty(page);
 		page_cache_release(page);
 		balance_dirty_pages_ratelimited(mapping);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c587e2d..8639169 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -704,7 +704,7 @@ map_buffer_cached:
 				u8 *kaddr;
 				unsigned pofs;
 					
-				kaddr = kmap_atomic(page, KM_USER0);
+				kaddr = kmap_atomic(page);
 				if (bh_pos < pos) {
 					pofs = bh_pos & ~PAGE_CACHE_MASK;
 					memset(kaddr + pofs, 0, pos - bh_pos);
@@ -713,7 +713,7 @@ map_buffer_cached:
 					pofs = end & ~PAGE_CACHE_MASK;
 					memset(kaddr + pofs, 0, bh_end - end);
 				}
-				kunmap_atomic(kaddr, KM_USER0);
+				kunmap_atomic(kaddr);
 				flush_dcache_page(page);
 			}
 			continue;
@@ -1287,9 +1287,9 @@ static inline size_t ntfs_copy_from_user(struct page **pages,
 		len = PAGE_CACHE_SIZE - ofs;
 		if (len > bytes)
 			len = bytes;
-		addr = kmap_atomic(*pages, KM_USER0);
+		addr = kmap_atomic(*pages);
 		left = __copy_from_user_inatomic(addr + ofs, buf, len);
-		kunmap_atomic(addr, KM_USER0);
+		kunmap_atomic(addr);
 		if (unlikely(left)) {
 			/* Do it the slow way. */
 			addr = kmap(*pages);
@@ -1401,10 +1401,10 @@ static inline size_t ntfs_copy_from_user_iovec(struct page **pages,
 		len = PAGE_CACHE_SIZE - ofs;
 		if (len > bytes)
 			len = bytes;
-		addr = kmap_atomic(*pages, KM_USER0);
+		addr = kmap_atomic(*pages);
 		copied = __ntfs_copy_from_user_iovec_inatomic(addr + ofs,
 				*iov, *iov_ofs, len);
-		kunmap_atomic(addr, KM_USER0);
+		kunmap_atomic(addr);
 		if (unlikely(copied != len)) {
 			/* Do it the slow way. */
 			addr = kmap(*pages);
@@ -1691,7 +1691,7 @@ static int ntfs_commit_pages_after_write(struct page **pages,
 	BUG_ON(end > le32_to_cpu(a->length) -
 			le16_to_cpu(a->data.resident.value_offset));
 	kattr = (u8*)a + le16_to_cpu(a->data.resident.value_offset);
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	/* Copy the received data from the page to the mft record. */
 	memcpy(kattr + pos, kaddr + pos, bytes);
 	/* Update the attribute length if necessary. */
@@ -1713,7 +1713,7 @@ static int ntfs_commit_pages_after_write(struct page **pages,
 		flush_dcache_page(page);
 		SetPageUptodate(page);
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	/* Update initialized_size/i_size if necessary. */
 	read_lock_irqsave(&ni->size_lock, flags);
 	initialized_size = ni->initialized_size;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 5a4a8af..f0974e2 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2475,7 +2475,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
 			nr_free -= PAGE_CACHE_SIZE * 8;
 			continue;
 		}
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		/*
 		 * Subtract the number of set bits. If this
 		 * is the last page and it is partial we don't really care as
@@ -2485,7 +2485,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
 		 */
 		nr_free -= bitmap_weight(kaddr,
 					PAGE_CACHE_SIZE * BITS_PER_BYTE);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		page_cache_release(page);
 	}
 	ntfs_debug("Finished reading $Bitmap, last index = 0x%lx.", index - 1);
@@ -2546,7 +2546,7 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
 			nr_free -= PAGE_CACHE_SIZE * 8;
 			continue;
 		}
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		/*
 		 * Subtract the number of set bits. If this
 		 * is the last page and it is partial we don't really care as
@@ -2556,7 +2556,7 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
 		 */
 		nr_free -= bitmap_weight(kaddr,
 					PAGE_CACHE_SIZE * BITS_PER_BYTE);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		page_cache_release(page);
 	}
 	ntfs_debug("Finished reading $MFT/$BITMAP, last index = 0x%lx.",
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 78b68af..6577432 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -102,7 +102,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
 		 * copy, the data is still good. */
 		if (buffer_jbd(buffer_cache_bh)
 		    && ocfs2_inode_is_new(inode)) {
-			kaddr = kmap_atomic(bh_result->b_page, KM_USER0);
+			kaddr = kmap_atomic(bh_result->b_page);
 			if (!kaddr) {
 				mlog(ML_ERROR, "couldn't kmap!\n");
 				goto bail;
@@ -110,7 +110,7 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,
 			memcpy(kaddr + (bh_result->b_size * iblock),
 			       buffer_cache_bh->b_data,
 			       bh_result->b_size);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			set_buffer_uptodate(bh_result);
 		}
 		brelse(buffer_cache_bh);
@@ -236,13 +236,13 @@ int ocfs2_read_inline_data(struct inode *inode, struct page *page,
 		return -EROFS;
 	}
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (size)
 		memcpy(kaddr, di->id2.i_data.id_data, size);
 	/* Clear the remaining part of the page */
 	memset(kaddr + size, 0, PAGE_CACHE_SIZE - size);
 	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	SetPageUptodate(page);
 
@@ -689,7 +689,7 @@ static void ocfs2_clear_page_regions(struct page *page,
 
 	ocfs2_figure_cluster_boundaries(osb, cpos, &cluster_start, &cluster_end);
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 
 	if (from || to) {
 		if (from > cluster_start)
@@ -700,7 +700,7 @@ static void ocfs2_clear_page_regions(struct page *page,
 		memset(kaddr + cluster_start, 0, cluster_end - cluster_start);
 	}
 
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 /*
@@ -1981,9 +1981,9 @@ static void ocfs2_write_end_inline(struct inode *inode, loff_t pos,
 		}
 	}
 
-	kaddr = kmap_atomic(wc->w_target_page, KM_USER0);
+	kaddr = kmap_atomic(wc->w_target_page);
 	memcpy(di->id2.i_data.id_data + pos, kaddr + pos, *copied);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	trace_ocfs2_write_end_inline(
 	     (unsigned long long)OCFS2_I(inode)->ip_blkno,
diff --git a/fs/pipe.c b/fs/pipe.c
index a932ced..fe0502f 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -230,7 +230,7 @@ void *generic_pipe_buf_map(struct pipe_inode_info *pipe,
 {
 	if (atomic) {
 		buf->flags |= PIPE_BUF_FLAG_ATOMIC;
-		return kmap_atomic(buf->page, KM_USER0);
+		return kmap_atomic(buf->page);
 	}
 
 	return kmap(buf->page);
@@ -251,7 +251,7 @@ void generic_pipe_buf_unmap(struct pipe_inode_info *pipe,
 {
 	if (buf->flags & PIPE_BUF_FLAG_ATOMIC) {
 		buf->flags &= ~PIPE_BUF_FLAG_ATOMIC;
-		kunmap_atomic(map_data, KM_USER0);
+		kunmap_atomic(map_data);
 	} else
 		kunmap(buf->page);
 }
@@ -565,14 +565,14 @@ redo1:
 			iov_fault_in_pages_read(iov, chars);
 redo2:
 			if (atomic)
-				src = kmap_atomic(page, KM_USER0);
+				src = kmap_atomic(page);
 			else
 				src = kmap(page);
 
 			error = pipe_iov_copy_from_user(src, iov, chars,
 							atomic);
 			if (atomic)
-				kunmap_atomic(src, KM_USER0);
+				kunmap_atomic(src);
 			else
 				kunmap(page);
 
diff --git a/fs/pnode.c b/fs/pnode.c
index ab5fa9e..bed378d 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -257,12 +257,12 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 		prev_src_mnt  = child;
 	}
 out:
-	br_write_lock(vfsmount_lock);
+	br_write_lock(&vfsmount_lock);
 	while (!list_empty(&tmp_list)) {
 		child = list_first_entry(&tmp_list, struct mount, mnt_hash);
 		umount_tree(child, 0, &umount_list);
 	}
-	br_write_unlock(vfsmount_lock);
+	br_write_unlock(&vfsmount_lock);
 	release_mounts(&umount_list);
 	return ret;
 }
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 84fd323..d839bfd 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -32,6 +32,7 @@ static void proc_evict_inode(struct inode *inode)
 	struct proc_dir_entry *de;
 	struct ctl_table_header *head;
 	const struct proc_ns_operations *ns_ops;
+	void *ns;
 
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
@@ -50,8 +51,9 @@ static void proc_evict_inode(struct inode *inode)
 	}
 	/* Release any associated namespace */
 	ns_ops = PROC_I(inode)->ns_ops;
-	if (ns_ops && ns_ops->put)
-		ns_ops->put(PROC_I(inode)->ns);
+	ns = PROC_I(inode)->ns;
+	if (ns_ops && ns)
+		ns_ops->put(ns);
 }
 
 static struct kmem_cache * proc_inode_cachep;
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index 27da860..6ca5c43 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -30,6 +30,140 @@ static const struct file_operations ns_file_operations = {
 	.llseek		= no_llseek,
 };
 
+static const struct inode_operations ns_inode_operations = {
+	.setattr	= proc_setattr,
+};
+
+static int ns_delete_dentry(const struct dentry *dentry)
+{
+	/* Don't cache namespace dentries when not in use */
+	return 1;
+}
+
+static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
+
+	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
+		ns_ops->name, inode->i_ino);
+}
+
+static const struct dentry_operations ns_dentry_operations =
+{
+	.d_delete	= ns_delete_dentry,
+	.d_dname	= ns_dname,
+};
+
+static struct dentry *proc_ns_get_dentry(struct super_block *sb,
+	struct task_struct *task, const struct proc_ns_operations *ns_ops)
+{
+	struct dentry *dentry;
+	struct inode *inode;
+	struct proc_inode *ei;
+	struct qstr qname = { .name = "", };
+	void *ns;
+
+	ns = ns_ops->get(task);
+	if (!ns)
+		return ERR_PTR(-ENOENT);
+
+	dentry = d_alloc_pseudo(sb, &qname);
+	if (!dentry) {
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	inode = new_inode(sb);
+	if (!inode) {
+		dput(dentry);
+		ns_ops->put(ns);
+		return ERR_PTR(-ENOMEM);
+	}
+		
+	ei = PROC_I(inode);
+	inode->i_ino = get_next_ino();
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	inode->i_op = &ns_inode_operations;
+	inode->i_mode = S_IFREG|S_IRUSR;
+	inode->i_fop = &ns_file_operations;
+	ei->ns_ops = ns_ops;
+	ei->ns = ns;
+
+	d_set_d_op(dentry, &ns_dentry_operations);
+	d_instantiate(dentry, inode);
+
+	return dentry;
+}
+
+static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	struct inode *inode = dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	struct proc_inode *ei = PROC_I(inode);
+	struct task_struct *task;
+	struct dentry *ns_dentry;
+	void *error = ERR_PTR(-EACCES);
+	
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	ns_dentry = proc_ns_get_dentry(sb, task, ei->ns_ops);
+	if (IS_ERR(ns_dentry)) {
+		error = ERR_CAST(ns_dentry);
+		goto out_put_task;
+	}
+
+	dput(nd->path.dentry);
+	nd->path.dentry = ns_dentry;
+	error = NULL;
+
+out_put_task:
+	put_task_struct(task);
+out:
+	return error;
+}
+
+static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+{
+	struct inode *inode = dentry->d_inode;
+	struct proc_inode *ei = PROC_I(inode);
+	const struct proc_ns_operations *ns_ops = ei->ns_ops;
+	struct task_struct *task;
+	char name[50];
+	int len = -EACCES;
+
+	task = get_proc_task(inode);
+	if (!task)
+		goto out;
+
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
+		goto out_put_task;
+
+	snprintf(name, sizeof(name), "%s", ns_ops->name);
+	len = strlen(name);
+
+	if (len > buflen)
+		len = buflen;
+	if (copy_to_user(buffer, ns_ops->name, len))
+		len = -EFAULT;
+
+out_put_task:
+	put_task_struct(task);
+out:
+	return len;
+}
+
+static const struct inode_operations proc_ns_link_inode_operations = {
+	.readlink	= proc_ns_readlink,
+	.follow_link	= proc_ns_follow_link,
+	.setattr	= proc_setattr,
+};
+
 static struct dentry *proc_ns_instantiate(struct inode *dir,
 	struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
@@ -37,32 +171,23 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
 	struct inode *inode;
 	struct proc_inode *ei;
 	struct dentry *error = ERR_PTR(-ENOENT);
-	void *ns;
 
 	inode = proc_pid_make_inode(dir->i_sb, task);
 	if (!inode)
 		goto out;
 
-	ns = ns_ops->get(task);
-	if (!ns)
-		goto out_iput;
-
 	ei = PROC_I(inode);
-	inode->i_mode = S_IFREG|S_IRUSR;
-	inode->i_fop  = &ns_file_operations;
-	ei->ns_ops    = ns_ops;
-	ei->ns	      = ns;
+	inode->i_mode = S_IFLNK|S_IRWXUGO;
+	inode->i_op = &proc_ns_link_inode_operations;
+	ei->ns_ops = ns_ops;
 
-	dentry->d_op = &pid_dentry_operations;
+	d_set_d_op(dentry, &pid_dentry_operations);
 	d_add(dentry, inode);
 	/* Close the race of the process dying before we return the dentry */
 	if (pid_revalidate(dentry, NULL))
 		error = NULL;
 out:
 	return error;
-out_iput:
-	iput(inode);
-	goto out;
 }
 
 static int proc_ns_fill_cache(struct file *filp, void *dirent,
@@ -89,10 +214,6 @@ static int proc_ns_dir_readdir(struct file *filp, void *dirent,
 	if (!task)
 		goto out_no_task;
 
-	ret = -EPERM;
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	ret = 0;
 	i = filp->f_pos;
 	switch (i) {
@@ -152,10 +273,6 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 	if (!task)
 		goto out_no_task;
 
-	error = ERR_PTR(-EPERM);
-	if (!ptrace_may_access(task, PTRACE_MODE_READ))
-		goto out;
-
 	last = &ns_entries[ARRAY_SIZE(ns_entries) - 1];
 	for (entry = ns_entries; entry <= last; entry++) {
 		if (strlen((*entry)->name) != len)
@@ -163,7 +280,6 @@ static struct dentry *proc_ns_dir_lookup(struct inode *dir,
 		if (!memcmp(dentry->d_name.name, (*entry)->name, len))
 			break;
 	}
-	error = ERR_PTR(-ENOENT);
 	if (entry > last)
 		goto out;
 
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a6b6217..d82f4a8 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -59,17 +59,11 @@ out:
 
 static struct ctl_table *find_in_table(struct ctl_table *p, struct qstr *name)
 {
-	int len;
 	for ( ; p->procname; p++) {
-
-		if (!p->procname)
-			continue;
-
-		len = strlen(p->procname);
-		if (len != name->len)
+		if (strlen(p->procname) != name->len)
 			continue;
 
-		if (memcmp(p->procname, name->name, len) != 0)
+		if (memcmp(p->procname, name->name, name->len) != 0)
 			continue;
 
 		/* I have a match */
@@ -266,10 +260,6 @@ static int scan(struct ctl_table_header *head, ctl_table *table,
 	for (; table->procname; table++, (*pos)++) {
 		int res;
 
-		/* Can't do anything without a proc name */
-		if (!table->procname)
-			continue;
-
 		if (*pos < file->f_pos)
 			continue;
 
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index e418c5a..7dcd2a2 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -518,6 +518,9 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
 		if (!page)
 			continue;
 
+		if (PageReserved(page))
+			continue;
+
 		/* Clear accessed and referenced bits. */
 		ptep_test_and_clear_young(vma, addr, pte);
 		ClearPageReferenced(page);
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index 1241285..5e289a7 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -23,12 +23,12 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
 
 	poll_wait(file, &p->ns->poll, wait);
 
-	br_read_lock(vfsmount_lock);
+	br_read_lock(&vfsmount_lock);
 	if (p->m.poll_event != ns->event) {
 		p->m.poll_event = ns->event;
 		res |= POLLERR | POLLPRI;
 	}
-	br_read_unlock(vfsmount_lock);
+	br_read_unlock(&vfsmount_lock);
 
 	return res;
 }
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 5ec59b2..4674197 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2125,6 +2125,8 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
 		mutex_unlock(&dqopt->dqio_mutex);
 		goto out_file_init;
 	}
+	if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
+		dqopt->info[type].dqi_flags |= DQF_SYS_FILE;
 	mutex_unlock(&dqopt->dqio_mutex);
 	spin_lock(&dq_state_lock);
 	dqopt->flags |= dquot_state_flag(flags, type);
@@ -2464,7 +2466,7 @@ int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
 	spin_lock(&dq_data_lock);
 	ii->dqi_bgrace = mi->dqi_bgrace;
 	ii->dqi_igrace = mi->dqi_igrace;
-	ii->dqi_flags = mi->dqi_flags & DQF_MASK;
+	ii->dqi_flags = mi->dqi_flags & DQF_GETINFO_MASK;
 	ii->dqi_valid = IIF_ALL;
 	spin_unlock(&dq_data_lock);
 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
@@ -2490,8 +2492,8 @@ int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
 	if (ii->dqi_valid & IIF_IGRACE)
 		mi->dqi_igrace = ii->dqi_igrace;
 	if (ii->dqi_valid & IIF_FLAGS)
-		mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) |
-				(ii->dqi_flags & DQF_MASK);
+		mi->dqi_flags = (mi->dqi_flags & ~DQF_SETINFO_MASK) |
+				(ii->dqi_flags & DQF_SETINFO_MASK);
 	spin_unlock(&dq_data_lock);
 	mark_info_dirty(sb, type);
 	/* Force write to disk */
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index 313d39d..77df82f 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -1284,12 +1284,12 @@ int reiserfs_delete_item(struct reiserfs_transaction_handle *th,
 		 ** -clm
 		 */
 
-		data = kmap_atomic(un_bh->b_page, KM_USER0);
+		data = kmap_atomic(un_bh->b_page);
 		off = ((le_ih_k_offset(&s_ih) - 1) & (PAGE_CACHE_SIZE - 1));
 		memcpy(data + off,
 		       B_I_PITEM(PATH_PLAST_BUFFER(path), &s_ih),
 		       ret_value);
-		kunmap_atomic(data, KM_USER0);
+		kunmap_atomic(data);
 	}
 	/* Perform balancing after all resources have been collected at once. */
 	do_balance(&s_del_balance, NULL, NULL, M_DELETE);
diff --git a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c
index d7f6e51..8f546bd 100644
--- a/fs/reiserfs/tail_conversion.c
+++ b/fs/reiserfs/tail_conversion.c
@@ -128,9 +128,9 @@ int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
 	if (up_to_date_bh) {
 		unsigned pgoff =
 		    (tail_offset + total_tail - 1) & (PAGE_CACHE_SIZE - 1);
-		char *kaddr = kmap_atomic(up_to_date_bh->b_page, KM_USER0);
+		char *kaddr = kmap_atomic(up_to_date_bh->b_page);
 		memset(kaddr + pgoff, 0, blk_size - total_tail);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 
 	REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
diff --git a/fs/splice.c b/fs/splice.c
index 1ec0493..f16402e 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -737,15 +737,12 @@ int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 		goto out;
 
 	if (buf->page != page) {
-		/*
-		 * Careful, ->map() uses KM_USER0!
-		 */
 		char *src = buf->ops->map(pipe, buf, 1);
-		char *dst = kmap_atomic(page, KM_USER1);
+		char *dst = kmap_atomic(page);
 
 		memcpy(dst + offset, src + buf->offset, this_len);
 		flush_dcache_page(page);
-		kunmap_atomic(dst, KM_USER1);
+		kunmap_atomic(dst);
 		buf->ops->unmap(pipe, buf, src);
 	}
 	ret = pagecache_write_end(file, mapping, sd->pos, this_len, this_len,
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
index 38bb1c6..8ca62c2 100644
--- a/fs/squashfs/file.c
+++ b/fs/squashfs/file.c
@@ -464,10 +464,10 @@ static int squashfs_readpage(struct file *file, struct page *page)
 		if (PageUptodate(push_page))
 			goto skip_page;
 
-		pageaddr = kmap_atomic(push_page, KM_USER0);
+		pageaddr = kmap_atomic(push_page);
 		squashfs_copy_data(pageaddr, buffer, offset, avail);
 		memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
-		kunmap_atomic(pageaddr, KM_USER0);
+		kunmap_atomic(pageaddr);
 		flush_dcache_page(push_page);
 		SetPageUptodate(push_page);
 skip_page:
@@ -484,9 +484,9 @@ skip_page:
 error_out:
 	SetPageError(page);
 out:
-	pageaddr = kmap_atomic(page, KM_USER0);
+	pageaddr = kmap_atomic(page);
 	memset(pageaddr, 0, PAGE_CACHE_SIZE);
-	kunmap_atomic(pageaddr, KM_USER0);
+	kunmap_atomic(pageaddr);
 	flush_dcache_page(page);
 	if (!PageError(page))
 		SetPageUptodate(page);
diff --git a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c
index 1191817..12806df 100644
--- a/fs/squashfs/symlink.c
+++ b/fs/squashfs/symlink.c
@@ -90,14 +90,14 @@ static int squashfs_symlink_readpage(struct file *file, struct page *page)
 			goto error_out;
 		}
 
-		pageaddr = kmap_atomic(page, KM_USER0);
+		pageaddr = kmap_atomic(page);
 		copied = squashfs_copy_data(pageaddr + bytes, entry, offset,
 								length - bytes);
 		if (copied == length - bytes)
 			memset(pageaddr + length, 0, PAGE_CACHE_SIZE - length);
 		else
 			block = entry->next_index;
-		kunmap_atomic(pageaddr, KM_USER0);
+		kunmap_atomic(pageaddr);
 		squashfs_cache_put(entry);
 	}
 
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index f9c234b..5c8f6dc 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1042,10 +1042,10 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
 	 * the page size, the remaining memory is zeroed when mapped, and
 	 * writes to that region are not written out to the file."
 	 */
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memset(kaddr + len, 0, PAGE_CACHE_SIZE - len);
 	flush_dcache_page(page);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	if (i_size > synced_i_size) {
 		err = inode->i_sb->s_op->write_inode(inode, NULL);
diff --git a/fs/udf/file.c b/fs/udf/file.c
index dca0c38..c088507 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -87,10 +87,10 @@ static int udf_adinicb_write_end(struct file *file,
 	char *kaddr;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset,
 		kaddr + offset, copied);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	return simple_write_end(file, mapping, pos, len, copied, page, fsdata);
 }
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 4fd95a3..3744d2a 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -25,28 +25,6 @@
 #include <linux/scatterlist.h>
 #include <linux/sched.h>
 
-static inline enum km_type crypto_kmap_type(int out)
-{
-	enum km_type type;
-
-	if (in_softirq())
-		type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0;
-	else
-		type = out * (KM_USER1 - KM_USER0) + KM_USER0;
-
-	return type;
-}
-
-static inline void *crypto_kmap(struct page *page, int out)
-{
-	return kmap_atomic(page, crypto_kmap_type(out));
-}
-
-static inline void crypto_kunmap(void *vaddr, int out)
-{
-	kunmap_atomic(vaddr, crypto_kmap_type(out));
-}
-
 static inline void crypto_yield(u32 flags)
 {
 	if (flags & CRYPTO_TFM_REQ_MAY_SLEEP)
@@ -121,15 +99,15 @@ static inline struct page *scatterwalk_page(struct scatter_walk *walk)
 	return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
 }
 
-static inline void scatterwalk_unmap(void *vaddr, int out)
+static inline void scatterwalk_unmap(void *vaddr)
 {
-	crypto_kunmap(vaddr, out);
+	kunmap_atomic(vaddr);
 }
 
 void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
 void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
 			    size_t nbytes, int out);
-void *scatterwalk_map(struct scatter_walk *walk, int out);
+void *scatterwalk_map(struct scatter_walk *walk);
 void scatterwalk_done(struct scatter_walk *walk, int out, int more);
 
 void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index c37c342..bc9ec1d 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -17,7 +17,7 @@
 
 /*****************************************************************************/
 /*
- * the payload for a key of type "user"
+ * the payload for a key of type "user" or "logon"
  * - once filled in and attached to a key:
  *   - the payload struct is invariant may not be changed, only replaced
  *   - the payload must be read with RCU procedures or with the key semaphore
@@ -33,6 +33,7 @@ struct user_key_payload {
 };
 
 extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
 
 extern int user_instantiate(struct key *key, const void *data, size_t datalen);
 extern int user_update(struct key *key, const void *data, size_t datalen);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index c94e717..60c447b 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -3,6 +3,7 @@ header-y += can/
 header-y += caif/
 header-y += dvb/
 header-y += hdlc/
+header-y += hsi/
 header-y += isdn/
 header-y += mmc/
 header-y += nfsd/
@@ -17,6 +18,7 @@ header-y += netfilter_bridge/
 header-y += netfilter_ipv4/
 header-y += netfilter_ipv6/
 header-y += usb/
+header-y += xshm/
 header-y += wimax/
 
 objhdr-y += version.h
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 129a9c0..de5422a 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -101,10 +101,10 @@ static inline int bio_has_allocated_vec(struct bio *bio)
  * I/O completely on that queue (see ide-dma for example)
  */
 #define __bio_kmap_atomic(bio, idx, kmtype)				\
-	(kmap_atomic(bio_iovec_idx((bio), (idx))->bv_page, kmtype) +	\
+	(kmap_atomic(bio_iovec_idx((bio), (idx))->bv_page) +	\
 		bio_iovec_idx((bio), (idx))->bv_offset)
 
-#define __bio_kunmap_atomic(addr, kmtype) kunmap_atomic(addr, kmtype)
+#define __bio_kunmap_atomic(addr, kmtype) kunmap_atomic(addr)
 
 /*
  * merge helpers etc
@@ -317,7 +317,7 @@ static inline char *bvec_kmap_irq(struct bio_vec *bvec, unsigned long *flags)
 	 * balancing is a lot nicer this way
 	 */
 	local_irq_save(*flags);
-	addr = (unsigned long) kmap_atomic(bvec->bv_page, KM_BIO_SRC_IRQ);
+	addr = (unsigned long) kmap_atomic(bvec->bv_page);
 
 	BUG_ON(addr & ~PAGE_MASK);
 
@@ -328,7 +328,7 @@ static inline void bvec_kunmap_irq(char *buffer, unsigned long *flags)
 {
 	unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
 
-	kunmap_atomic((void *) ptr, KM_BIO_SRC_IRQ);
+	kunmap_atomic((void *) ptr);
 	local_irq_restore(*flags);
 }
 
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 3c1063a..a3b6b82 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -27,11 +27,22 @@ extern unsigned long __sw_hweight64(__u64 w);
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
 
 /* same as for_each_set_bit() but use bit as value to start with */
-#define for_each_set_bit_cont(bit, addr, size) \
+#define for_each_set_bit_from(bit, addr, size) \
 	for ((bit) = find_next_bit((addr), (size), (bit));	\
 	     (bit) < (size);					\
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+#define for_each_clear_bit(bit, addr, size) \
+	for ((bit) = find_first_zero_bit((addr), (size));	\
+	     (bit) < (size);					\
+	     (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
+
+/* same as for_each_clear_bit() but use bit as value to start with */
+#define for_each_clear_bit_from(bit, addr, size) \
+	for ((bit) = find_next_zero_bit((addr), (size), (bit));	\
+	     (bit) < (size);					\
+	     (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
+
 static __inline__ int get_bitmask_order(unsigned int count)
 {
 	int order;
@@ -56,6 +67,26 @@ static inline unsigned long hweight_long(unsigned long w)
 }
 
 /**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 rol64(__u64 word, unsigned int shift)
+{
+	return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 ror64(__u64 word, unsigned int shift)
+{
+	return (word >> shift) | (word << (64 - shift));
+}
+
+/**
  * rol32 - rotate a 32-bit value left
  * @word: value to rotate
  * @shift: bits to roll
diff --git a/include/linux/c2c_genio.h b/include/linux/c2c_genio.h
new file mode 100644
index 0000000..d356472
--- /dev/null
+++ b/include/linux/c2c_genio.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __INC_GENIO_H
+#define __INC_GENIO_H
+#include <linux/types.h>
+
+/**
+ * DOC: C2C GENI/GENO interface.
+ *
+ * This API defines the API for the C2C driver and the GENI/GENO registers.
+ */
+
+/**
+ * enum GENIO_BITS - Definition of special GENIO BITS.
+ * @READY_FOR_IPC_BIT:  Remote side is ready for IPC.
+ * This GENI/GENO bit is triggered when ring-buffer protocol
+ * is enabled from the remote end (modem)
+ *
+ * @READY_FOR_CAIF_BIT: Remote side is ready for CAIF.
+ * This GENI/GENO bit is triggered when CAIF protocol
+ * is enabled from the remote end (modem)
+ */
+enum GENIO_BITS {
+	READY_FOR_CAIF_BIT = 28,
+	READY_FOR_IPC_BIT = 29
+};
+
+/**
+ * genio_subscribe - Subscribe for notifications on bit-change of GENI/O bits.
+ *
+ * @bit:	The GENI/O bit where we want to be called back when it changes.
+ *
+ * @bit_set_cb:	Callback function to be called when the requested GENI/O bit
+ *		is set by the external device (modem).
+ *
+ * @data: Client data to be provided in the callback function.
+ *
+ * Install a callback function for a GENI/O bit. Returns negative upon error.
+ *
+ * The genio driver is expected to handle the 4-state handshake for geni/geno
+ * update, for the bit this function subscribe to. This function may block,
+ * and cannot be called from IRQ context.
+ *
+ * Returns zero on success, and negative upon error.
+ *
+ * Precondition: This function is called after genio_set_shm_addr() and
+ * genio_bit_alloc(). @bit must be defined as as getter in genio_bit_alloc().
+ *
+ * Callback context:
+ *		The "bit_set_cb" callback must be called from the
+ *		IRQ context. The callback function is not allowed to block
+ *		or spend much CPU time in the callback, It must defer
+ *		work to soft-IRQ or work queues.
+ */
+int genio_subscribe(int bit, void (*bit_set_cb)(void *data), void *data);
+
+/**
+ * genio_unsubscribe - Unsubscribe for callback  GENI/O bit.
+ * @bit:       The GENI/O bit to we want release.
+ *
+ * This function may block. It returns zero on success, and negative upon error.
+ *
+ * Precondition: @bit must be defined as as getter in genio_bit_alloc().
+ */
+int genio_unsubscribe(int bit);
+
+/**
+ * genio_bit_alloc - Allocate the usage of GENI/O bits.
+ *
+ * @setter_mask:	Bit-mask defining the bits that can be set by
+ *			genio_set_bit()
+ * @getter_mask:	Bit-mask defining the bits that can be subscribed by
+ *			genio_subscribe().
+ *
+ * The @getter_mask defines the bit for RX direction, i.e. bits that can
+ * be subscribed by the function genio_subscribe().
+ * The @setter_mask defines the bit for TX direction, i.e. bits that can
+ * be set by the function genio_set_bit().
+ * This function may block.
+ *
+ * Returns zero on success, and negative upon error.
+ *
+ * Precondition:
+ * This function cannot be called before ipc_ready_cb() has been called,
+ * and must be called prior to any call on genio_subscribe() or genio_set_bit().
+ *
+ */
+int genio_bit_alloc(u32 setter_mask, u32 getter_mask);
+
+/**
+ * genio_set_shm_addr - Inform remote device about the shared memory address.
+ * @addr:		The shared memory address.
+ * @ipc_ready_cb:	The callback function indicating IPC is ready.
+ *
+ * Description:
+ * Implements the setting of shared memory address involving the
+ * READY_FOR_IPC GENIO bits, and READY_FOR_IPC handshaking.
+ * When handshaking is done ipc_ready_cb is called.
+ * The usage of this bit is during start/restart.
+ * This function may block.
+ *
+ * When the ipc_ready_cb() with @ready=%true, Stream channels can be opened.
+ *
+ * Sequence:
+ * (1) Write the address to the GENO register,
+ *
+ * (2) wait for interrupt on IPC_READY (set to one in GENI register)
+ *
+ * (3) write zero to the GENO register
+ *
+ * (4) wait for interrupt on IPC_READY (set to zero)
+ *
+ * (5) call the callback function for IPC_READY
+ *
+ * Returns zero on success, and negative upon error.
+ *
+ * Precondition:
+ * This function must be called initially upon start, or after remote device
+ * has been reset.
+ */
+int genio_set_shm_addr(u32 addr, void (*ipc_ready_cb) (void));
+
+/**
+ * genio_subscribe_caif_ready - Notify that CAIF channels can be
+ * opened.
+ *
+ * @caif_ready_cb: is called with @ready = %true in the start up sequence,
+ * when the remote side is ready for CAIF enumeration. Upon reset,
+ * caif_ready_cb() will be called with @ready = %false.
+ *
+ * The %READY_FOR_CAIF_BIT is set to %one as long as the
+ * modem is able to run CAIF traffic. Upon modem restart/crash it will
+ * be set back to %zero.
+ * This function may block.
+ *
+ * Returns zero on success, and negative upon error.
+ */
+int genio_subscribe_caif_ready(void (*caif_ready_cb) (bool ready));
+
+/**
+ * genio_register_errhandler - Register an error handler.
+ *
+ * @errhandler: error handler called from driver upon severe errors
+ *		that requires reset of the remote device.
+ */
+void genio_register_errhandler(void (*errhandler)(int errno));
+
+/**
+ * genio_reset() - Reset the C2C driver
+ *
+ * Reset the C2C Driver due to remote device restart.
+ * This shall reset state back to initial state, and should only
+ * be used when remote device (modem) has reset.
+ *
+ * All settings, subscriptions and state information in the driver must
+ * be reset. GENIO client must do all subscriptions again.
+ * This function may block.
+ *
+ * Returns zero on success, and negative upon error.
+ */
+int genio_reset(void);
+
+/**
+ * genio_set_bit() -	Set a single GENI/O bit.
+ *
+ * @bit:	The GENI/O bit to set
+ *
+ * This function is used to signal over GENI/GENO the driver must
+ * perform the 4-state protocol to signal the change to remote device.
+ * This function is non-blocking, and can be called from Soft-IRQ context.
+ *
+ * Returns zero on success, and negative upon error.
+ *
+ * Precondition: @bit must be defined as as setter in genio_bit_alloc().
+ */
+int genio_set_bit(int bit);
+
+/**
+ * genio_power_req() -	Request power on on remote C2C block.
+ *
+ * @state:	1 - power-on request , 0 - power-off request
+ *
+ * This function will request power on of remote C2C block.
+ * This function is non-blocking, and can be called from Soft-IRQ context.
+ *
+ * Returns zero on success, and negative upon error.
+ */
+int genio_power_req(int state);
+
+#endif /*INC_GENIO_H*/
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 41c9f65..c7f22d3 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -224,6 +224,7 @@ struct compat_sysinfo;
 struct compat_sysctl_args;
 struct compat_kexec_segment;
 struct compat_mq_attr;
+struct compat_msgbuf;
 
 extern void compat_exit_robust_list(struct task_struct *curr);
 
@@ -234,13 +235,22 @@ asmlinkage long
 compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
 			   compat_size_t __user *len_ptr);
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_semctl(int first, int second, int third, void __user *uptr);
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
 long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 		int version, void __user *uptr);
-long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
 		void __user *uptr);
+#else
+long compat_sys_semctl(int semid, int semnum, int cmd, int arg);
+long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
+		size_t msgsz, int msgflg);
+long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
+		size_t msgsz, long msgtyp, int msgflg);
+long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg);
+#endif
+long compat_sys_msgctl(int first, int second, void __user *uptr);
 long compat_sys_shmctl(int first, int second, void __user *uptr);
 long compat_sys_semtimedop(int semid, struct sembuf __user *tsems,
 		unsigned nsems, const struct compat_timespec __user *timeout);
diff --git a/include/linux/crc32.h b/include/linux/crc32.h
index 391a259..68267b6 100644
--- a/include/linux/crc32.h
+++ b/include/linux/crc32.h
@@ -11,6 +11,8 @@
 extern u32  crc32_le(u32 crc, unsigned char const *p, size_t len);
 extern u32  crc32_be(u32 crc, unsigned char const *p, size_t len);
 
+extern u32  __crc32c_le(u32 crc, unsigned char const *p, size_t len);
+
 #define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)(data), length)
 
 /*
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 8a94217..a8fa654 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -75,6 +75,11 @@
  */
 #define CRYPTO_ALG_INSTANCE		0x00000800
 
+/* Set this bit if the algorithm provided is hardware accelerated but
+ * not available to userspace via instruction set or so.
+ */
+#define CRYPTO_ALG_KERN_DRIVER_ONLY	0x00001000
+
 /*
  * Transform masks and values (for crt_flags).
  */
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index 6c6133f..b5fac2b 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -36,9 +36,12 @@
 #define FAN_UNLIMITED_QUEUE	0x00000010
 #define FAN_UNLIMITED_MARKS	0x00000020
 
+/* Attempt read-only open if read-write failed. */
+#define FAN_READONLY_FALLBACK  0x00000040
+
 #define FAN_ALL_INIT_FLAGS	(FAN_CLOEXEC | FAN_NONBLOCK | \
 				 FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
-				 FAN_UNLIMITED_MARKS)
+				 FAN_UNLIMITED_MARKS | FAN_READONLY_FALLBACK)
 
 /* flags used for fanotify_modify_mark() */
 #define FAN_MARK_ADD		0x00000001
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 91d0e0a3..226c791 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -125,6 +125,7 @@ struct fsnotify_group {
 
 	const struct fsnotify_ops *ops;	/* how this group handles things */
 
+	struct mutex mutex;
 	/* needed to send notification to userspace */
 	struct mutex notification_mutex;	/* protect the notification_list */
 	struct list_head notification_list;	/* list of event_holder this group needs to send to userspace */
@@ -168,6 +169,7 @@ struct fsnotify_group {
 			wait_queue_head_t access_waitq;
 			atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
+			bool readonly_fallback;
 			int f_flags;
 			unsigned int max_marks;
 			struct user_struct *user;
@@ -415,8 +417,6 @@ extern void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group);
 extern void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group, unsigned int flags);
 /* run all the marks in a group, and flag them to be freed */
 extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group);
-extern void fsnotify_get_mark(struct fsnotify_mark *mark);
-extern void fsnotify_put_mark(struct fsnotify_mark *mark);
 extern void fsnotify_unmount_inodes(struct list_head *list);
 
 /* put here because inotify does some weird stuff when destroying watches */
@@ -430,6 +430,16 @@ extern struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_ev
 extern int fsnotify_replace_event(struct fsnotify_event_holder *old_holder,
 				  struct fsnotify_event *new_event);
 
+static inline void fsnotify_get_mark(struct fsnotify_mark *mark)
+{
+	atomic_inc(&mark->refcnt);
+}
+
+static inline void fsnotify_put_mark(struct fsnotify_mark *mark)
+{
+	if (atomic_dec_and_test(&mark->refcnt))
+		mark->free_mark(mark);
+}
 #else
 
 static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 8ba2c94..bc18853 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -54,6 +54,7 @@
  * 7.18
  *  - add FUSE_IOCTL_DIR flag
  *  - add FUSE_NOTIFY_DELETE
+ *  - add FUSE_MMAP and FUSE_MUNMAP
  */
 
 #ifndef _LINUX_FUSE_H
@@ -278,6 +279,8 @@ enum fuse_opcode {
 	FUSE_POLL          = 40,
 	FUSE_NOTIFY_REPLY  = 41,
 	FUSE_BATCH_FORGET  = 42,
+	FUSE_MMAP          = 43,
+	FUSE_MUNMAP        = 44,
 
 	/* CUSE specific operations */
 	CUSE_INIT          = 4096,
@@ -571,6 +574,28 @@ struct fuse_notify_poll_wakeup_out {
 	__u64	kh;
 };
 
+struct fuse_mmap_in {
+	__u64	fh;
+	__u64	addr;
+	__u64	len;
+	__u32	prot;
+	__u32	flags;
+	__u64	offset;
+};
+
+struct fuse_mmap_out {
+	__u64	mapid;		/* Mmap ID, same namespace as Inode ID */
+	__u64	size;		/* Size of memory region */
+	__u64	reserved;
+};
+
+struct fuse_munmap_in {
+	__u64	fh;
+	__u64	mapid;
+	__u64	size;		/* Size of memory region */
+	__u64	reserved;
+};
+
 struct fuse_in_header {
 	__u32	len;
 	__u32	opcode;
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 3a93f73..6549ed7 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -55,12 +55,12 @@ static inline void kunmap(struct page *page)
 {
 }
 
-static inline void *__kmap_atomic(struct page *page)
+static inline void *kmap_atomic(struct page *page)
 {
 	pagefault_disable();
 	return page_address(page);
 }
-#define kmap_atomic_prot(page, prot)	__kmap_atomic(page)
+#define kmap_atomic_prot(page, prot)	kmap_atomic(page)
 
 static inline void __kunmap_atomic(void *addr)
 {
@@ -109,27 +109,62 @@ static inline void kmap_atomic_idx_pop(void)
 #endif
 
 /*
- * Make both: kmap_atomic(page, idx) and kmap_atomic(page) work.
+ * NOTE:
+ * kmap_atomic() and kunmap_atomic() with two arguments are deprecated.
+ * We only keep them for backward compatibility, any usage of them
+ * are now warned.
  */
-#define kmap_atomic(page, args...) __kmap_atomic(page)
+
+#define PASTE(a, b) a ## b
+#define PASTE2(a, b) PASTE(a, b)
+
+#define NARG_(_2, _1, n, ...) n
+#define NARG(...) NARG_(__VA_ARGS__, 2, 1, :)
+
+static inline void __deprecated *kmap_atomic_deprecated(struct page *page,
+							enum km_type km)
+{
+	return kmap_atomic(page);
+}
+
+#define kmap_atomic1(...) kmap_atomic(__VA_ARGS__)
+#define kmap_atomic2(...) kmap_atomic_deprecated(__VA_ARGS__)
+#define kmap_atomic(...) PASTE2(kmap_atomic, NARG(__VA_ARGS__)(__VA_ARGS__))
+
+static inline void __deprecated __kunmap_atomic_deprecated(void *addr,
+							enum km_type km)
+{
+	__kunmap_atomic(addr);
+}
 
 /*
  * Prevent people trying to call kunmap_atomic() as if it were kunmap()
  * kunmap_atomic() should get the return value of kmap_atomic, not the page.
  */
-#define kunmap_atomic(addr, args...)				\
-do {								\
-	BUILD_BUG_ON(__same_type((addr), struct page *));	\
-	__kunmap_atomic(addr);					\
+#define kunmap_atomic_deprecated(addr, km)                      \
+do {                                                            \
+	BUILD_BUG_ON(__same_type((addr), struct page *));       \
+	__kunmap_atomic_deprecated(addr, km);                   \
 } while (0)
 
+#define kunmap_atomic_withcheck(addr)                           \
+do {                                                            \
+	BUILD_BUG_ON(__same_type((addr), struct page *));       \
+	__kunmap_atomic(addr);                                  \
+} while (0)
+
+#define kunmap_atomic1(...) kunmap_atomic_withcheck(__VA_ARGS__)
+#define kunmap_atomic2(...) kunmap_atomic_deprecated(__VA_ARGS__)
+#define kunmap_atomic(...) PASTE2(kunmap_atomic, NARG(__VA_ARGS__)(__VA_ARGS__))
+/**** End of C pre-processor tricks for deprecated macros ****/
+
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
 #ifndef clear_user_highpage
 static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
 {
-	void *addr = kmap_atomic(page, KM_USER0);
+	void *addr = kmap_atomic(page);
 	clear_user_page(addr, vaddr, page);
-	kunmap_atomic(addr, KM_USER0);
+	kunmap_atomic(addr);
 }
 #endif
 
@@ -180,16 +215,16 @@ alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
 
 static inline void clear_highpage(struct page *page)
 {
-	void *kaddr = kmap_atomic(page, KM_USER0);
+	void *kaddr = kmap_atomic(page);
 	clear_page(kaddr);
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 
 static inline void zero_user_segments(struct page *page,
 	unsigned start1, unsigned end1,
 	unsigned start2, unsigned end2)
 {
-	void *kaddr = kmap_atomic(page, KM_USER0);
+	void *kaddr = kmap_atomic(page);
 
 	BUG_ON(end1 > PAGE_SIZE || end2 > PAGE_SIZE);
 
@@ -199,7 +234,7 @@ static inline void zero_user_segments(struct page *page,
 	if (end2 > start2)
 		memset(kaddr + start2, 0, end2 - start2);
 
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 	flush_dcache_page(page);
 }
 
@@ -228,11 +263,11 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
 {
 	char *vfrom, *vto;
 
-	vfrom = kmap_atomic(from, KM_USER0);
-	vto = kmap_atomic(to, KM_USER1);
+	vfrom = kmap_atomic(from);
+	vto = kmap_atomic(to);
 	copy_user_page(vto, vfrom, vaddr, to);
-	kunmap_atomic(vto, KM_USER1);
-	kunmap_atomic(vfrom, KM_USER0);
+	kunmap_atomic(vto);
+	kunmap_atomic(vfrom);
 }
 
 #endif
@@ -241,11 +276,11 @@ static inline void copy_highpage(struct page *to, struct page *from)
 {
 	char *vfrom, *vto;
 
-	vfrom = kmap_atomic(from, KM_USER0);
-	vto = kmap_atomic(to, KM_USER1);
+	vfrom = kmap_atomic(from);
+	vto = kmap_atomic(to);
 	copy_page(vto, vfrom);
-	kunmap_atomic(vto, KM_USER1);
-	kunmap_atomic(vfrom, KM_USER0);
+	kunmap_atomic(vto);
+	kunmap_atomic(vfrom);
 }
 
 #endif /* _LINUX_HIGHMEM_H */
diff --git a/include/linux/hpet.h b/include/linux/hpet.h
index 219ca4f..d690c0f 100644
--- a/include/linux/hpet.h
+++ b/include/linux/hpet.h
@@ -125,6 +125,7 @@ struct hpet_info {
 #define	HPET_EPI	_IO('h', 0x04)	/* enable periodic */
 #define	HPET_DPI	_IO('h', 0x05)	/* disable periodic */
 #define	HPET_IRQFREQ	_IOW('h', 0x6, unsigned long)	/* IRQFREQ usec */
+#define	HPET_ALLOC_TIMER _IO('h', 0x7)
 
 #define MAX_HPET_TBS	8		/* maximum hpet timer blocks */
 
diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild
new file mode 100644
index 0000000..271a770
--- /dev/null
+++ b/include/linux/hsi/Kbuild
@@ -0,0 +1 @@
+header-y += hsi_char.h
diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
new file mode 100644
index 0000000..4b17806
--- /dev/null
+++ b/include/linux/hsi/hsi.h
@@ -0,0 +1,410 @@
+/*
+ * HSI core header file.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_H__
+#define __LINUX_HSI_H__
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+/* HSI message ttype */
+#define HSI_MSG_READ	0
+#define HSI_MSG_WRITE	1
+
+/* HSI configuration values */
+enum {
+	HSI_MODE_STREAM	= 1,
+	HSI_MODE_FRAME,
+};
+
+enum {
+	HSI_FLOW_SYNC,	/* Synchronized flow */
+	HSI_FLOW_PIPE,	/* Pipelined flow */
+};
+
+enum {
+	HSI_ARB_RR,	/* Round-robin arbitration */
+	HSI_ARB_PRIO,	/* Channel priority arbitration */
+};
+
+#define HSI_MAX_CHANNELS	16
+
+/* HSI message status codes */
+enum {
+	HSI_STATUS_COMPLETED,	/* Message transfer is completed */
+	HSI_STATUS_PENDING,	/* Message pending to be read/write (POLL) */
+	HSI_STATUS_PROCEEDING,	/* Message transfer is ongoing */
+	HSI_STATUS_QUEUED,	/* Message waiting to be served */
+	HSI_STATUS_ERROR,	/* Error when message transfer was ongoing */
+};
+
+/* HSI port event codes */
+enum {
+	HSI_EVENT_START_RX,
+	HSI_EVENT_STOP_RX,
+};
+
+/**
+ * struct hsi_config - Configuration for RX/TX HSI modules
+ * @mode: Bit transmission mode (STREAM or FRAME)
+ * @channels: Number of channels to use [1..16]
+ * @speed: Max bit transmission speed (Kbit/s)
+ * @flow: RX flow type (SYNCHRONIZED or PIPELINE)
+ * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
+ */
+struct hsi_config {
+	unsigned int	mode;
+	unsigned int	channels;
+	unsigned int	speed;
+	union {
+		unsigned int	flow;		/* RX only */
+		unsigned int	arb_mode;	/* TX only */
+	};
+};
+
+/**
+ * struct hsi_board_info - HSI client board info
+ * @name: Name for the HSI device
+ * @hsi_id: HSI controller id where the client sits
+ * @port: Port number in the controller where the client sits
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @platform_data: Platform related data
+ * @archdata: Architecture-dependent device data
+ */
+struct hsi_board_info {
+	const char		*name;
+	unsigned int		hsi_id;
+	unsigned int		port;
+	struct hsi_config	tx_cfg;
+	struct hsi_config	rx_cfg;
+	void			*platform_data;
+	struct dev_archdata	*archdata;
+};
+
+#ifdef CONFIG_HSI_BOARDINFO
+extern int hsi_register_board_info(struct hsi_board_info const *info,
+							unsigned int len);
+#else
+static inline int hsi_register_board_info(struct hsi_board_info const *info,
+							unsigned int len)
+{
+	return 0;
+}
+#endif /* CONFIG_HSI_BOARDINFO */
+
+/**
+ * struct hsi_client - HSI client attached to an HSI port
+ * @device: Driver model representation of the device
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @hsi_start_rx: Called after incoming wake line goes high
+ * @hsi_stop_rx: Called after incoming wake line goes low
+ */
+struct hsi_client {
+	struct device		device;
+	struct hsi_config	tx_cfg;
+	struct hsi_config	rx_cfg;
+	void			(*hsi_start_rx)(struct hsi_client *cl);
+	void			(*hsi_stop_rx)(struct hsi_client *cl);
+	/* private: */
+	unsigned int		pclaimed:1;
+	struct list_head	link;
+};
+
+#define to_hsi_client(dev) container_of(dev, struct hsi_client, device)
+
+static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data)
+{
+	dev_set_drvdata(&cl->device, data);
+}
+
+static inline void *hsi_client_drvdata(struct hsi_client *cl)
+{
+	return dev_get_drvdata(&cl->device);
+}
+
+/**
+ * struct hsi_client_driver - Driver associated to an HSI client
+ * @driver: Driver model representation of the driver
+ */
+struct hsi_client_driver {
+	struct device_driver	driver;
+};
+
+#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\
+									driver)
+
+int hsi_register_client_driver(struct hsi_client_driver *drv);
+
+static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+
+/**
+ * struct hsi_msg - HSI message descriptor
+ * @link: Free to use by the current descriptor owner
+ * @cl: HSI device client that issues the transfer
+ * @sgt: Head of the scatterlist array
+ * @context: Client context data associated to the transfer
+ * @complete: Transfer completion callback
+ * @destructor: Destructor to free resources when flushing
+ * @status: Status of the transfer when completed
+ * @actual_len: Actual length of data transfered on completion
+ * @channel: Channel were to TX/RX the message
+ * @ttype: Transfer type (TX if set, RX otherwise)
+ * @break_frame: if true HSI will send/receive a break frame. Data buffers are
+ *		ignored in the request.
+ */
+struct hsi_msg {
+	struct list_head	link;
+	struct hsi_client	*cl;
+	struct sg_table		sgt;
+	void			*context;
+
+	void			(*complete)(struct hsi_msg *msg);
+	void			(*destructor)(struct hsi_msg *msg);
+
+	int			status;
+	unsigned int		actual_len;
+	unsigned int		channel;
+	unsigned int		ttype:1;
+	unsigned int		break_frame:1;
+};
+
+struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags);
+void hsi_free_msg(struct hsi_msg *msg);
+
+/**
+ * struct hsi_port - HSI port device
+ * @device: Driver model representation of the device
+ * @tx_cfg: Current TX path configuration
+ * @rx_cfg: Current RX path configuration
+ * @num: Port number
+ * @shared: Set when port can be shared by different clients
+ * @claimed: Reference count of clients which claimed the port
+ * @lock: Serialize port claim
+ * @async: Asynchronous transfer callback
+ * @setup: Callback to set the HSI client configuration
+ * @flush: Callback to clean the HW state and destroy all pending transfers
+ * @start_tx: Callback to inform that a client wants to TX data
+ * @stop_tx: Callback to inform that a client no longer wishes to TX data
+ * @release: Callback to inform that a client no longer uses the port
+ * @clients: List of hsi_clients using the port.
+ * @clock: Lock to serialize access to the clients list.
+ */
+struct hsi_port {
+	struct device			device;
+	struct hsi_config		tx_cfg;
+	struct hsi_config		rx_cfg;
+	unsigned int			num;
+	unsigned int			shared:1;
+	int				claimed;
+	struct mutex			lock;
+	int				(*async)(struct hsi_msg *msg);
+	int				(*setup)(struct hsi_client *cl);
+	int				(*flush)(struct hsi_client *cl);
+	int				(*start_tx)(struct hsi_client *cl);
+	int				(*stop_tx)(struct hsi_client *cl);
+	int				(*release)(struct hsi_client *cl);
+	struct list_head		clients;
+	spinlock_t			clock;
+};
+
+#define to_hsi_port(dev) container_of(dev, struct hsi_port, device)
+#define hsi_get_port(cl) to_hsi_port((cl)->device.parent)
+
+void hsi_event(struct hsi_port *port, unsigned int event);
+int hsi_claim_port(struct hsi_client *cl, unsigned int share);
+void hsi_release_port(struct hsi_client *cl);
+
+static inline int hsi_port_claimed(struct hsi_client *cl)
+{
+	return cl->pclaimed;
+}
+
+static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data)
+{
+	dev_set_drvdata(&port->device, data);
+}
+
+static inline void *hsi_port_drvdata(struct hsi_port *port)
+{
+	return dev_get_drvdata(&port->device);
+}
+
+/**
+ * struct hsi_controller - HSI controller device
+ * @device: Driver model representation of the device
+ * @owner: Pointer to the module owning the controller
+ * @id: HSI controller ID
+ * @num_ports: Number of ports in the HSI controller
+ * @port: Array of HSI ports
+ */
+struct hsi_controller {
+	struct device		device;
+	struct module		*owner;
+	unsigned int		id;
+	unsigned int		num_ports;
+	struct hsi_port		*port;
+};
+
+#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device)
+
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
+void hsi_free_controller(struct hsi_controller *hsi);
+int hsi_register_controller(struct hsi_controller *hsi);
+void hsi_unregister_controller(struct hsi_controller *hsi);
+
+static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi,
+								void *data)
+{
+	dev_set_drvdata(&hsi->device, data);
+}
+
+static inline void *hsi_controller_drvdata(struct hsi_controller *hsi)
+{
+	return dev_get_drvdata(&hsi->device);
+}
+
+static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
+							unsigned int num)
+{
+	return (num < hsi->num_ports) ? &hsi->port[num] : NULL;
+}
+
+/*
+ * API for HSI clients
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg);
+
+/**
+ * hsi_id - Get HSI controller ID associated to a client
+ * @cl: Pointer to a HSI client
+ *
+ * Return the controller id where the client is attached to
+ */
+static inline unsigned int hsi_id(struct hsi_client *cl)
+{
+	return	to_hsi_controller(cl->device.parent->parent)->id;
+}
+
+/**
+ * hsi_port_id - Gets the port number a client is attached to
+ * @cl: Pointer to HSI client
+ *
+ * Return the port number associated to the client
+ */
+static inline unsigned int hsi_port_id(struct hsi_client *cl)
+{
+	return	to_hsi_port(cl->device.parent)->num;
+}
+
+/**
+ * hsi_setup - Configure the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * When sharing ports, clients should either relay on a single
+ * client setup or have the same setup for all of them.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_setup(struct hsi_client *cl)
+{
+	if (!hsi_port_claimed(cl))
+		return -EACCES;
+	return	hsi_get_port(cl)->setup(cl);
+}
+
+/**
+ * hsi_flush - Flush all pending transactions on the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * This function will destroy all pending hsi_msg in the port and reset
+ * the HW port so it is ready to receive and transmit from a clean state.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_flush(struct hsi_client *cl)
+{
+	if (!hsi_port_claimed(cl))
+		return -EACCES;
+	return hsi_get_port(cl)->flush(cl);
+}
+
+/**
+ * hsi_async_read - Submit a read transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg)
+{
+	msg->ttype = HSI_MSG_READ;
+	return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_async_write - Submit a write transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg)
+{
+	msg->ttype = HSI_MSG_WRITE;
+	return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_start_tx - Signal the port that the client wants to start a TX
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_start_tx(struct hsi_client *cl)
+{
+	if (!hsi_port_claimed(cl))
+		return -EACCES;
+	return hsi_get_port(cl)->start_tx(cl);
+}
+
+/**
+ * hsi_stop_tx - Signal the port that the client no longer wants to transmit
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_stop_tx(struct hsi_client *cl)
+{
+	if (!hsi_port_claimed(cl))
+		return -EACCES;
+	return hsi_get_port(cl)->stop_tx(cl);
+}
+#endif /* __LINUX_HSI_H__ */
diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h
new file mode 100644
index 0000000..76160b4
--- /dev/null
+++ b/include/linux/hsi/hsi_char.h
@@ -0,0 +1,63 @@
+/*
+ * Part of the HSI character device driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos at nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+#ifndef __HSI_CHAR_H
+#define __HSI_CHAR_H
+
+#define HSI_CHAR_MAGIC		'k'
+#define HSC_IOW(num, dtype)	_IOW(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOR(num, dtype)	_IOR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOWR(num, dtype)	_IOWR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IO(num)		_IO(HSI_CHAR_MAGIC, num)
+
+#define HSC_RESET		HSC_IO(16)
+#define HSC_SET_PM		HSC_IO(17)
+#define HSC_SEND_BREAK		HSC_IO(18)
+#define HSC_SET_RX		HSC_IOW(19, struct hsc_rx_config)
+#define HSC_GET_RX		HSC_IOW(20, struct hsc_rx_config)
+#define HSC_SET_TX		HSC_IOW(21, struct hsc_tx_config)
+#define HSC_GET_TX		HSC_IOW(22, struct hsc_tx_config)
+
+#define HSC_PM_DISABLE		0
+#define HSC_PM_ENABLE		1
+
+#define HSC_MODE_STREAM		1
+#define HSC_MODE_FRAME		2
+#define HSC_FLOW_SYNC		0
+#define HSC_ARB_RR		0
+#define HSC_ARB_PRIO		1
+
+struct hsc_rx_config {
+	uint32_t mode;
+	uint32_t flow;
+	uint32_t channels;
+};
+
+struct hsc_tx_config {
+	uint32_t mode;
+	uint32_t channels;
+	uint32_t speed;
+	uint32_t arb_mode;
+};
+
+#endif /* __HSI_CHAR_H */
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 2fa0901..0d7d6a1 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -50,9 +50,11 @@
  * note header.  For kdump, the code in vmcore.c runs in the context
  * of the second kernel to combine them into one note.
  */
+#ifndef KEXEC_NOTE_BYTES
 #define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) +		\
 			    KEXEC_CORE_NOTE_NAME_BYTES +		\
 			    KEXEC_CORE_NOTE_DESC_BYTES )
+#endif
 
 /*
  * This structure is used to hold the arguments that are used when loading
diff --git a/include/linux/lglock.h b/include/linux/lglock.h
index 87f402c..5152056 100644
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -23,28 +23,17 @@
 #include <linux/lockdep.h>
 #include <linux/percpu.h>
 #include <linux/cpu.h>
+#include <linux/notifier.h>
 
 /* can make br locks by using local lock for read side, global lock for write */
-#define br_lock_init(name)	name##_lock_init()
-#define br_read_lock(name)	name##_local_lock()
-#define br_read_unlock(name)	name##_local_unlock()
-#define br_write_lock(name)	name##_global_lock_online()
-#define br_write_unlock(name)	name##_global_unlock_online()
+#define br_lock_init(name)	lg_lock_init(name, #name)
+#define br_read_lock(name)	lg_local_lock(name)
+#define br_read_unlock(name)	lg_local_unlock(name)
+#define br_write_lock(name)	lg_global_lock_online(name)
+#define br_write_unlock(name)	lg_global_unlock_online(name)
 
-#define DECLARE_BRLOCK(name)	DECLARE_LGLOCK(name)
 #define DEFINE_BRLOCK(name)	DEFINE_LGLOCK(name)
 
-
-#define lg_lock_init(name)	name##_lock_init()
-#define lg_local_lock(name)	name##_local_lock()
-#define lg_local_unlock(name)	name##_local_unlock()
-#define lg_local_lock_cpu(name, cpu)	name##_local_lock_cpu(cpu)
-#define lg_local_unlock_cpu(name, cpu)	name##_local_unlock_cpu(cpu)
-#define lg_global_lock(name)	name##_global_lock()
-#define lg_global_unlock(name)	name##_global_unlock()
-#define lg_global_lock_online(name) name##_global_lock_online()
-#define lg_global_unlock_online(name) name##_global_unlock_online()
-
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 #define LOCKDEP_INIT_MAP lockdep_init_map
 
@@ -59,142 +48,34 @@
 #define DEFINE_LGLOCK_LOCKDEP(name)
 #endif
 
+struct lglock {
+	arch_spinlock_t __percpu *lock;
+	cpumask_t cpus;	/* XXX need to put on separate cacheline? */
+	spinlock_t cpu_lock;
+	struct notifier_block cpu_notifier;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lock_class_key lock_key;
+	struct lockdep_map    lock_dep_map;
+#endif
+};
+
+#define DEFINE_LGLOCK(name) \
+	DEFINE_PER_CPU(arch_spinlock_t, name ## _lock) = __ARCH_SPIN_LOCK_UNLOCKED; \
+	struct lglock name = { .lock = &name ## _lock, 				\
+			       .cpu_lock = __SPIN_LOCK_UNLOCKED(cpu_lock), 	\
+			       .cpu_notifier.notifier_call = lg_cpu_callback }
+
+/* Only valid for statics */
+void lg_lock_init(struct lglock *lg, char *name);
+void lg_local_lock(struct lglock *lg);
+void lg_local_unlock(struct lglock *lg);
+void lg_local_lock_cpu(struct lglock *lg, int cpu);
+void lg_local_unlock_cpu(struct lglock *lg, int cpu);
+void lg_global_lock_online(struct lglock *lg);
+void lg_global_unlock_online(struct lglock *lg);
+void lg_global_lock(struct lglock *lg);
+void lg_global_unlock(struct lglock *lg);
 
-#define DECLARE_LGLOCK(name)						\
- extern void name##_lock_init(void);					\
- extern void name##_local_lock(void);					\
- extern void name##_local_unlock(void);					\
- extern void name##_local_lock_cpu(int cpu);				\
- extern void name##_local_unlock_cpu(int cpu);				\
- extern void name##_global_lock(void);					\
- extern void name##_global_unlock(void);				\
- extern void name##_global_lock_online(void);				\
- extern void name##_global_unlock_online(void);				\
+int lg_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu);
 
-#define DEFINE_LGLOCK(name)						\
-									\
- DEFINE_SPINLOCK(name##_cpu_lock);					\
- cpumask_t name##_cpus __read_mostly;					\
- DEFINE_PER_CPU(arch_spinlock_t, name##_lock);				\
- DEFINE_LGLOCK_LOCKDEP(name);						\
-									\
- static int								\
- name##_lg_cpu_callback(struct notifier_block *nb,			\
-				unsigned long action, void *hcpu)	\
- {									\
-	switch (action & ~CPU_TASKS_FROZEN) {				\
-	case CPU_UP_PREPARE:						\
-		spin_lock(&name##_cpu_lock);				\
-		cpu_set((unsigned long)hcpu, name##_cpus);		\
-		spin_unlock(&name##_cpu_lock);				\
-		break;							\
-	case CPU_UP_CANCELED: case CPU_DEAD:				\
-		spin_lock(&name##_cpu_lock);				\
-		cpu_clear((unsigned long)hcpu, name##_cpus);		\
-		spin_unlock(&name##_cpu_lock);				\
-	}								\
-	return NOTIFY_OK;						\
- }									\
- static struct notifier_block name##_lg_cpu_notifier = {		\
-	.notifier_call = name##_lg_cpu_callback,			\
- };									\
- void name##_lock_init(void) {						\
-	int i;								\
-	LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \
-	for_each_possible_cpu(i) {					\
-		arch_spinlock_t *lock;					\
-		lock = &per_cpu(name##_lock, i);			\
-		*lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;	\
-	}								\
-	register_hotcpu_notifier(&name##_lg_cpu_notifier);		\
-	get_online_cpus();						\
-	for_each_online_cpu(i)						\
-		cpu_set(i, name##_cpus);				\
-	put_online_cpus();						\
- }									\
- EXPORT_SYMBOL(name##_lock_init);					\
-									\
- void name##_local_lock(void) {						\
-	arch_spinlock_t *lock;						\
-	preempt_disable();						\
-	rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_);	\
-	lock = &__get_cpu_var(name##_lock);				\
-	arch_spin_lock(lock);						\
- }									\
- EXPORT_SYMBOL(name##_local_lock);					\
-									\
- void name##_local_unlock(void) {					\
-	arch_spinlock_t *lock;						\
-	rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_);		\
-	lock = &__get_cpu_var(name##_lock);				\
-	arch_spin_unlock(lock);						\
-	preempt_enable();						\
- }									\
- EXPORT_SYMBOL(name##_local_unlock);					\
-									\
- void name##_local_lock_cpu(int cpu) {					\
-	arch_spinlock_t *lock;						\
-	preempt_disable();						\
-	rwlock_acquire_read(&name##_lock_dep_map, 0, 0, _THIS_IP_);	\
-	lock = &per_cpu(name##_lock, cpu);				\
-	arch_spin_lock(lock);						\
- }									\
- EXPORT_SYMBOL(name##_local_lock_cpu);					\
-									\
- void name##_local_unlock_cpu(int cpu) {				\
-	arch_spinlock_t *lock;						\
-	rwlock_release(&name##_lock_dep_map, 1, _THIS_IP_);		\
-	lock = &per_cpu(name##_lock, cpu);				\
-	arch_spin_unlock(lock);						\
-	preempt_enable();						\
- }									\
- EXPORT_SYMBOL(name##_local_unlock_cpu);				\
-									\
- void name##_global_lock_online(void) {					\
-	int i;								\
-	spin_lock(&name##_cpu_lock);					\
-	rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_);		\
-	for_each_cpu(i, &name##_cpus) {					\
-		arch_spinlock_t *lock;					\
-		lock = &per_cpu(name##_lock, i);			\
-		arch_spin_lock(lock);					\
-	}								\
- }									\
- EXPORT_SYMBOL(name##_global_lock_online);				\
-									\
- void name##_global_unlock_online(void) {				\
-	int i;								\
-	rwlock_release(&name##_lock_dep_map, 1, _RET_IP_);		\
-	for_each_cpu(i, &name##_cpus) {					\
-		arch_spinlock_t *lock;					\
-		lock = &per_cpu(name##_lock, i);			\
-		arch_spin_unlock(lock);					\
-	}								\
-	spin_unlock(&name##_cpu_lock);					\
- }									\
- EXPORT_SYMBOL(name##_global_unlock_online);				\
-									\
- void name##_global_lock(void) {					\
-	int i;								\
-	preempt_disable();						\
-	rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_);		\
-	for_each_possible_cpu(i) {					\
-		arch_spinlock_t *lock;					\
-		lock = &per_cpu(name##_lock, i);			\
-		arch_spin_lock(lock);					\
-	}								\
- }									\
- EXPORT_SYMBOL(name##_global_lock);					\
-									\
- void name##_global_unlock(void) {					\
-	int i;								\
-	rwlock_release(&name##_lock_dep_map, 1, _RET_IP_);		\
-	for_each_possible_cpu(i) {					\
-		arch_spinlock_t *lock;					\
-		lock = &per_cpu(name##_lock, i);			\
-		arch_spin_unlock(lock);					\
-	}								\
-	preempt_enable();						\
- }									\
- EXPORT_SYMBOL(name##_global_unlock);
 #endif
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 4d34356..bf4e1f4 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -396,7 +396,7 @@ static inline void mem_cgroup_replace_page_cache(struct page *oldpage,
 static inline void mem_cgroup_reset_owner(struct page *page)
 {
 }
-#endif /* CONFIG_CGROUP_MEM_CONT */
+#endif /* CONFIG_CGROUP_MEM_RES_CTLR */
 
 #if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM)
 static inline bool
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 17b27cd..36b5909 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1385,6 +1385,7 @@ extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 extern int install_special_mapping(struct mm_struct *mm,
 				   unsigned long addr, unsigned long len,
 				   unsigned long flags, struct page **pages);
+extern bool is_special_mapping(struct vm_area_struct *vma);
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 3cc3062..81a56df 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -12,6 +12,7 @@
 #include <linux/completion.h>
 #include <linux/cpumask.h>
 #include <linux/page-debug-flags.h>
+#include <linux/uprobes.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
 
@@ -354,6 +355,7 @@ struct mm_struct {
 	unsigned int faultstamp;
 	unsigned int token_priority;
 	unsigned int last_interval;
+	atomic_t active_swap_token;
 
 	unsigned long flags; /* Must use atomic bitops to access the bits */
 
@@ -388,6 +390,10 @@ struct mm_struct {
 #ifdef CONFIG_CPUMASK_OFFSTACK
 	struct cpumask cpumask_allocation;
 #endif
+#ifdef CONFIG_UPROBES
+	atomic_t mm_uprobes_count;
+	struct uprobes_xol_area *uprobes_xol_area;
+#endif
 };
 
 static inline void mm_init_cpumask(struct mm_struct *mm)
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 9f22ba5..f9a0663 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -71,6 +71,8 @@ struct mmc_ext_csd {
 	bool			hpi_en;			/* HPI enablebit */
 	bool			hpi;			/* HPI support bit */
 	unsigned int		hpi_cmd;		/* cmd used as HPI */
+	unsigned int            data_sector_size;       /* 512 bytes or 4KB */
+	unsigned int            data_tag_unit_size;     /* DATA TAG UNIT size */
 	unsigned int		boot_ro_lock;		/* ro lock support */
 	bool			boot_ro_lockable;
 	u8			raw_partition_support;	/* 160 */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index fb9f6e1..b822a2c 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -274,6 +274,7 @@ struct _mmc_csd {
 #define EXT_CSD_FLUSH_CACHE		32      /* W */
 #define EXT_CSD_CACHE_CTRL		33      /* R/W */
 #define EXT_CSD_POWER_OFF_NOTIFICATION	34	/* R/W */
+#define EXT_CSD_DATA_SECTOR_SIZE	61	/* R */
 #define EXT_CSD_GP_SIZE_MULT		143	/* R/W */
 #define EXT_CSD_PARTITION_ATTRIBUTE	156	/* R/W */
 #define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
@@ -315,6 +316,8 @@ struct _mmc_csd {
 #define EXT_CSD_POWER_OFF_LONG_TIME	247	/* RO */
 #define EXT_CSD_GENERIC_CMD6_TIME	248	/* RO */
 #define EXT_CSD_CACHE_SIZE		249	/* RO, 4 bytes */
+#define EXT_CSD_TAG_UNIT_SIZE		498	/* RO */
+#define EXT_CSD_DATA_TAG_SUPPORT	499	/* RO */
 #define EXT_CSD_HPI_FEATURES		503	/* RO */
 
 /*
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 650ba2f..887b032 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -795,7 +795,7 @@ static inline int is_dma(struct zone *zone)
 
 /* These two functions are used to setup the per zone pages min values */
 struct ctl_table;
-int min_free_kbytes_sysctl_handler(struct ctl_table *, int,
+int free_kbytes_sysctl_handler(struct ctl_table *, int,
 					void __user *, size_t *, loff_t *);
 extern int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1];
 int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int,
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index b29e7f6..92aef8a 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -414,6 +414,15 @@ struct hv_vmbus_device_id {
 			__attribute__((aligned(sizeof(kernel_ulong_t))));
 };
 
+/* rpmsg */
+
+#define RPMSG_NAME_SIZE			32
+#define RPMSG_DEVICE_MODALIAS_FMT	"rpmsg:%s"
+
+struct rpmsg_device_id {
+	char name[RPMSG_NAME_SIZE];
+};
+
 /* i2c */
 
 #define I2C_NAME_SIZE	20
diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h
index 1bbd9f2..ed270bd 100644
--- a/include/linux/mtd/blktrans.h
+++ b/include/linux/mtd/blktrans.h
@@ -47,6 +47,7 @@ struct mtd_blktrans_dev {
 	struct request_queue *rq;
 	spinlock_t queue_lock;
 	void *priv;
+	fmode_t file_mode;
 };
 
 struct mtd_blktrans_ops {
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 1a81fde..d8c7aad 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -427,9 +427,7 @@ static inline int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
-	if (!mtd->suspend)
-		return -EOPNOTSUPP;
-	return mtd->suspend(mtd);
+	return mtd->suspend ? mtd->suspend(mtd) : 0;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 63b5a8b..609868f 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -448,8 +448,9 @@ struct nand_buffers {
  *			will be copied to the appropriate nand_bbt_descr's.
  * @badblockpos:	[INTERN] position of the bad block marker in the oob
  *			area.
- * @badblockbits:	[INTERN] number of bits to left-shift the bad block
- *			number
+ * @badblockbits:	[INTERN] minimum number of set bits in a good block's
+ *			bad block marker position; i.e., BBM == 11110111b is
+ *			not bad when badblockbits == 7
  * @cellinfo:		[INTERN] MLC/multichip data from chip ident
  * @numchips:		[INTERN] number of physical chips
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h
new file mode 100644
index 0000000..a2ed4be
--- /dev/null
+++ b/include/linux/mtd/spear_smi.h
@@ -0,0 +1,62 @@
+/*
+ * include/linux/mtd/spear_smi.h
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Shiraz Hashim <shiraz.hashim@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MTD_SPEAR_SMI_H
+#define __MTD_SPEAR_SMI_H
+
+#include <linux/types.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+
+/* macro to define partitions for flash devices */
+#define DEFINE_PARTS(n, of, s)		\
+{					\
+	.name = n,			\
+	.offset = of,			\
+	.size = s,			\
+}
+
+/**
+ * struct spear_smi_flash_info - platform structure for passing flash
+ * information
+ *
+ * name: name of the serial nor flash for identification
+ * mem_base: the memory base on which the flash is mapped
+ * size: size of the flash in bytes
+ * partitions: parition details
+ * nr_partitions: number of partitions
+ * fast_mode: whether flash supports fast mode
+ */
+
+struct spear_smi_flash_info {
+	char *name;
+	unsigned long mem_base;
+	unsigned long size;
+	struct mtd_partition *partitions;
+	int nr_partitions;
+	u8 fast_mode;
+};
+
+/**
+ * struct spear_smi_plat_data - platform structure for configuring smi
+ *
+ * clk_rate: clk rate at which SMI must operate
+ * num_flashes: number of flashes present on board
+ * board_flash_info: specific details of each flash present on board
+ */
+struct spear_smi_plat_data {
+	unsigned long clk_rate;
+	int num_flashes;
+	struct spear_smi_flash_info *board_flash_info;
+};
+
+#endif /* __MTD_SPEAR_SMI_H */
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 32cd1f6..6e68d05 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -166,60 +166,6 @@ extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
 	(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))
 
 /*
- * Optional methods for optimized non-lvalue per-cpu variable access.
- *
- * @var can be a percpu variable or a field of it and its size should
- * equal char, int or long.  percpu_read() evaluates to a lvalue and
- * all others to void.
- *
- * These operations are guaranteed to be atomic.
- * The generic versions disable interrupts.  Archs are
- * encouraged to implement single-instruction alternatives which don't
- * require protection.
- */
-#ifndef percpu_read
-# define percpu_read(var)						\
-  ({									\
-	typeof(var) *pr_ptr__ = &(var);					\
-	typeof(var) pr_ret__;						\
-	pr_ret__ = get_cpu_var(*pr_ptr__);				\
-	put_cpu_var(*pr_ptr__);						\
-	pr_ret__;							\
-  })
-#endif
-
-#define __percpu_generic_to_op(var, val, op)				\
-do {									\
-	typeof(var) *pgto_ptr__ = &(var);				\
-	get_cpu_var(*pgto_ptr__) op val;				\
-	put_cpu_var(*pgto_ptr__);					\
-} while (0)
-
-#ifndef percpu_write
-# define percpu_write(var, val)		__percpu_generic_to_op(var, (val), =)
-#endif
-
-#ifndef percpu_add
-# define percpu_add(var, val)		__percpu_generic_to_op(var, (val), +=)
-#endif
-
-#ifndef percpu_sub
-# define percpu_sub(var, val)		__percpu_generic_to_op(var, (val), -=)
-#endif
-
-#ifndef percpu_and
-# define percpu_and(var, val)		__percpu_generic_to_op(var, (val), &=)
-#endif
-
-#ifndef percpu_or
-# define percpu_or(var, val)		__percpu_generic_to_op(var, (val), |=)
-#endif
-
-#ifndef percpu_xor
-# define percpu_xor(var, val)		__percpu_generic_to_op(var, (val), ^=)
-#endif
-
-/*
  * Branching function to split up a function into a set of functions that
  * are called for different scalar sizes of the objects handled.
  */
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 7ddc7f1..c492c75 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -114,4 +114,7 @@
 # define PR_SET_MM_START_BRK		6
 # define PR_SET_MM_BRK			7
 
+#define PR_SET_CHILD_SUBREAPER 36
+#define PR_GET_CHILD_SUBREAPER 37
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/quota.h b/include/linux/quota.h
index cb78556..c09fa04 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -230,7 +230,11 @@ struct mem_dqinfo {
 struct super_block;
 
 #define DQF_MASK 0xffff		/* Mask for format specific flags */
-#define DQF_INFO_DIRTY_B 16
+#define DQF_GETINFO_MASK 0x1ffff	/* Mask for flags passed to userspace */
+#define DQF_SETINFO_MASK 0xffff		/* Mask for flags modifiable from userspace */
+#define DQF_SYS_FILE_B		16
+#define DQF_SYS_FILE (1 << DQF_SYS_FILE_B)	/* Quota file stored as system file */
+#define DQF_INFO_DIRTY_B	31
 #define DQF_INFO_DIRTY (1 << DQF_INFO_DIRTY_B)	/* Is info dirty? */
 
 extern void mark_info_dirty(struct super_block *sb, int type);
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
new file mode 100644
index 0000000..b52f784
--- /dev/null
+++ b/include/linux/remoteproc.h
@@ -0,0 +1,264 @@
+/*
+ * Remote Processor Framework
+ *
+ * Copyright(c) 2011 Texas Instruments, Inc.
+ * Copyright(c) 2011 Google, Inc.
+ * 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 Texas Instruments 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 REMOTEPROC_H
+#define REMOTEPROC_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/klist.h>
+#include <linux/mutex.h>
+#include <linux/virtio.h>
+#include <linux/completion.h>
+
+/*
+ * The alignment between the consumer and producer parts of the vring.
+ * Note: this is part of the "wire" protocol. If you change this, you need
+ * to update your peers too.
+ */
+#define AMP_VRING_ALIGN	(4096)
+
+/**
+ * struct fw_resource - describes an entry from the resource section
+ * @type: resource type
+ * @id: index number of the resource
+ * @da: device address of the resource
+ * @pa: physical address of the resource
+ * @len: size, in bytes, of the resource
+ * @flags: properties of the resource, e.g. iommu protection required
+ * @reserved: must be 0 atm
+ * @name: name of resource
+ *
+ * The remote processor firmware should contain a "resource table":
+ * array of 'struct fw_resource' entries.
+ *
+ * Some resources entries are mere announcements, where the host is informed
+ * of specific remoteproc configuration. Other entries require the host to
+ * do something (e.g. reserve a requested resource) and possibly also reply
+ * by overwriting a member inside 'struct fw_resource' with info about the
+ * allocated resource.
+ *
+ * Different resource entries use different members of this struct,
+ * with different meanings. This is pretty limiting and error-prone,
+ * so the plan is to move to variable-length TLV-based resource entries,
+ * where each resource type will have its own structure.
+ */
+struct fw_resource {
+	u32 type;
+	u32 id;
+	u64 da;
+	u64 pa;
+	u32 len;
+	u32 flags;
+	u8 reserved[16];
+	u8 name[48];
+} __packed;
+
+/**
+ * enum fw_resource_type - types of resource entries
+ *
+ * @RSC_CARVEOUT:   request for allocation of a physically contiguous
+ *		    memory region.
+ * @RSC_DEVMEM:     request to iommu_map a memory-based peripheral.
+ * @RSC_TRACE:	    announces the availability of a trace buffer into which
+ *		    the remote processor will be writing logs. In this case,
+ *		    'da' indicates the device address where logs are written to,
+ *		    and 'len' is the size of the trace buffer.
+ * @RSC_VRING:	    request for allocation of a virtio vring (address should
+ *		    be indicated in 'da', and 'len' should contain the number
+ *		    of buffers supported by the vring).
+ * @RSC_VIRTIO_DEV: this entry declares about support for a virtio device,
+ *		    and serves as the virtio header. 'da' holds the
+ *		    the virtio device features, 'pa' holds the virtio guest
+ *		    features, 'len' holds the virtio status, and 'flags' holds
+ *		    the virtio id (currently only VIRTIO_ID_RPMSG is supported).
+ *
+ * Most of the resource entries share the basic idea of address/length
+ * negotiation with the host: the firmware usually asks (on behalf of the
+ * remote processor that will soon be booted with it) for memory
+ * of size 'len' bytes, and the host needs to allocate it and provide
+ * the device/physical address (when relevant) in 'da'/'pa' respectively.
+ *
+ * If the firmware is compiled with hard coded device addresses, and
+ * can't handle dynamically allocated 'da' values, then the 'da' field
+ * will contain the expected device addresses (today we actually only support
+ * this scheme, as there aren't yet any use cases for dynamically allocated
+ * device addresses).
+ */
+enum fw_resource_type {
+	RSC_CARVEOUT	= 0,
+	RSC_DEVMEM	= 1,
+	RSC_TRACE	= 2,
+	RSC_VRING	= 3,
+	RSC_VIRTIO_DEV	= 4,
+};
+
+/**
+ * struct rproc_mem_entry - memory entry descriptor
+ * @va:	virtual address
+ * @dma: dma address
+ * @len: length, in bytes
+ * @da: device address
+ * @priv: associated data
+ * @node: list node
+ */
+struct rproc_mem_entry {
+	void *va;
+	dma_addr_t dma;
+	int len;
+	u64 da;
+	void *priv;
+	struct list_head node;
+};
+
+struct rproc;
+
+/**
+ * struct rproc_ops - platform-specific device handlers
+ * @start:	power on the device and boot it
+ * @stop:	power off the device
+ * @kick:	kick a virtqueue (virtqueue id given as a parameter)
+ */
+struct rproc_ops {
+	int (*start)(struct rproc *rproc);
+	int (*stop)(struct rproc *rproc);
+	void (*kick)(struct rproc *rproc, int vqid);
+};
+
+/**
+ * enum rproc_state - remote processor states
+ * @RPROC_OFFLINE:	device is powered off
+ * @RPROC_SUSPENDED:	device is suspended; needs to be woken up to receive
+ *			a message.
+ * @RPROC_RUNNING:	device is up and running
+ * @RPROC_CRASHED:	device has crashed; need to start recovery
+ * @RPROC_LAST:		just keep this one at the end
+ *
+ * Please note that the values of these states are used as indices
+ * to rproc_state_string, a state-to-name lookup table,
+ * so please keep the two synchronized. @RPROC_LAST is used to check
+ * the validity of an index before the lookup table is accessed, so
+ * please update it as needed too.
+ */
+enum rproc_state {
+	RPROC_OFFLINE	= 0,
+	RPROC_SUSPENDED	= 1,
+	RPROC_RUNNING	= 2,
+	RPROC_CRASHED	= 3,
+	RPROC_LAST	= 4,
+};
+
+/**
+ * struct rproc - represents a physical remote processor device
+ * @node: klist node of this rproc object
+ * @domain: iommu domain
+ * @name: human readable name of the rproc
+ * @firmware: name of firmware file to be loaded
+ * @priv: private data which belongs to the platform-specific rproc module
+ * @ops: platform-specific start/stop rproc handlers
+ * @dev: underlying device
+ * @refcount: refcount of users that have a valid pointer to this rproc
+ * @power: refcount of users who need this rproc powered up
+ * @state: state of the device
+ * @lock: lock which protects concurrent manipulations of the rproc
+ * @dbg_dir: debugfs directory of this rproc device
+ * @traces: list of trace buffers
+ * @num_traces: number of trace buffers
+ * @carveouts: list of physically contiguous memory allocations
+ * @mappings: list of iommu mappings we initiated, needed on shutdown
+ * @firmware_loading_complete: marks e/o asynchronous firmware loading
+ * @bootaddr: address of first instruction to boot rproc with (optional)
+ * @rvdev: virtio device (we only support a single rpmsg virtio device for now)
+ */
+struct rproc {
+	struct klist_node node;
+	struct iommu_domain *domain;
+	const char *name;
+	const char *firmware;
+	void *priv;
+	const struct rproc_ops *ops;
+	struct device *dev;
+	struct kref refcount;
+	atomic_t power;
+	unsigned int state;
+	struct mutex lock;
+	struct dentry *dbg_dir;
+	struct list_head traces;
+	int num_traces;
+	struct list_head carveouts;
+	struct list_head mappings;
+	struct completion firmware_loading_complete;
+	u64 bootaddr;
+	struct rproc_vdev *rvdev;
+};
+
+/**
+ * struct rproc_vdev - remoteproc state for a supported virtio device
+ * @rproc: the rproc handle
+ * @vdev: the virio device
+ * @vq: the virtqueues for this vdev
+ * @vring: the vrings for this vdev
+ * @dfeatures: virtio device features
+ * @gfeatures: virtio guest features
+ */
+struct rproc_vdev {
+	struct rproc *rproc;
+	struct virtio_device vdev;
+	struct virtqueue *vq[2];
+	struct rproc_mem_entry vring[2];
+	unsigned long dfeatures;
+	unsigned long gfeatures;
+};
+
+struct rproc *rproc_get_by_name(const char *name);
+void rproc_put(struct rproc *rproc);
+
+struct rproc *rproc_alloc(struct device *dev, const char *name,
+				const struct rproc_ops *ops,
+				const char *firmware, int len);
+void rproc_free(struct rproc *rproc);
+int rproc_register(struct rproc *rproc);
+int rproc_unregister(struct rproc *rproc);
+
+int rproc_boot(struct rproc *rproc);
+void rproc_shutdown(struct rproc *rproc);
+
+static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev)
+{
+	struct rproc_vdev *rvdev = container_of(vdev, struct rproc_vdev, vdev);
+
+	return rvdev->rproc;
+}
+
+#endif /* REMOTEPROC_H */
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
new file mode 100644
index 0000000..a8e50e4
--- /dev/null
+++ b/include/linux/rpmsg.h
@@ -0,0 +1,326 @@
+/*
+ * Remote processor messaging
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ * 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 Texas Instruments 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 _LINUX_RPMSG_H
+#define _LINUX_RPMSG_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+/* The feature bitmap for virtio rpmsg */
+#define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
+
+/**
+ * struct rpmsg_hdr - common header for all rpmsg messages
+ * @src: source address
+ * @dst: destination address
+ * @reserved: reserved for future use
+ * @len: length of payload (in bytes)
+ * @flags: message flags
+ * @data: @len bytes of message payload data
+ *
+ * Every message sent(/received) on the rpmsg bus begins with this header.
+ */
+struct rpmsg_hdr {
+	u32 src;
+	u32 dst;
+	u32 reserved;
+	u16 len;
+	u16 flags;
+	u8 data[0];
+} __packed;
+
+/**
+ * struct rpmsg_ns_msg - dynamic name service announcement message
+ * @name: name of remote service that is published
+ * @addr: address of remote service that is published
+ * @flags: indicates whether service is created or destroyed
+ *
+ * This message is sent across to publish a new service, or announce
+ * about its removal. When we receive these messages, an appropriate
+ * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
+ * or ->remove() handler of the appropriate rpmsg driver will be invoked
+ * (if/as-soon-as one is registered).
+ */
+struct rpmsg_ns_msg {
+	char name[RPMSG_NAME_SIZE];
+	u32 addr;
+	u32 flags;
+} __packed;
+
+/**
+ * enum rpmsg_ns_flags - dynamic name service announcement flags
+ *
+ * @RPMSG_NS_CREATE: a new remote service was just created
+ * @RPMSG_NS_DESTROY: a known remote service was just destroyed
+ */
+enum rpmsg_ns_flags {
+	RPMSG_NS_CREATE		= 0,
+	RPMSG_NS_DESTROY	= 1,
+};
+
+#define RPMSG_ADDR_ANY		0xFFFFFFFF
+
+struct virtproc_info;
+
+/**
+ * rpmsg_channel - devices that belong to the rpmsg bus are called channels
+ * @vrp: the remote processor this channel belongs to
+ * @dev: the device struct
+ * @id: device id (used to match between rpmsg drivers and devices)
+ * @src: local address
+ * @dst: destination address
+ * @ept: the rpmsg endpoint of this channel
+ * @announce: if set, rpmsg will announce the creation/removal of this channel
+ */
+struct rpmsg_channel {
+	struct virtproc_info *vrp;
+	struct device dev;
+	struct rpmsg_device_id id;
+	u32 src;
+	u32 dst;
+	struct rpmsg_endpoint *ept;
+	bool announce;
+};
+
+typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
+
+/**
+ * struct rpmsg_endpoint - binds a local rpmsg address to its user
+ * @rpdev: rpmsg channel device
+ * @cb: rx callback handler
+ * @addr: local rpmsg address
+ * @priv: private data for the driver's use
+ *
+ * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
+ * it binds an rpmsg address with an rx callback handler.
+ *
+ * Simple rpmsg drivers shouldn't use this struct directly, because
+ * things just work: every rpmsg driver provides an rx callback upon
+ * registering to the bus, and that callback is then bound to its rpmsg
+ * address when the driver is probed. When relevant inbound messages arrive
+ * (i.e. messages which their dst address equals to the src address of
+ * the rpmsg channel), the driver's handler is invoked to process it.
+ *
+ * More complicated drivers though, that do need to allocate additional rpmsg
+ * addresses, and bind them to different rx callbacks, must explicitly
+ * create additional endpoints by themselves (see rpmsg_create_ept()).
+ */
+struct rpmsg_endpoint {
+	struct rpmsg_channel *rpdev;
+	rpmsg_rx_cb_t cb;
+	u32 addr;
+	void *priv;
+};
+
+/**
+ * struct rpmsg_driver - rpmsg driver struct
+ * @drv: underlying device driver
+ * @id_table: rpmsg ids serviced by this driver
+ * @probe: invoked when a matching rpmsg channel (i.e. device) is found
+ * @remove: invoked when the rpmsg channel is removed
+ * @callback: invoked when an inbound message is received on the channel
+ */
+struct rpmsg_driver {
+	struct device_driver drv;
+	const struct rpmsg_device_id *id_table;
+	int (*probe)(struct rpmsg_channel *dev);
+	void (*remove)(struct rpmsg_channel *dev);
+	void (*callback)(struct rpmsg_channel *, void *, int, void *, u32);
+};
+
+int register_rpmsg_device(struct rpmsg_channel *dev);
+void unregister_rpmsg_device(struct rpmsg_channel *dev);
+int register_rpmsg_driver(struct rpmsg_driver *drv);
+void unregister_rpmsg_driver(struct rpmsg_driver *drv);
+void rpmsg_destroy_ept(struct rpmsg_endpoint *);
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
+				rpmsg_rx_cb_t cb, void *priv, u32 addr);
+int
+rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @rpdev: the rpmsg channel
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @rpdev channel.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to, using @rpdev's source and destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
+{
+	u32 src = rpdev->src, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @rpdev: the rpmsg channel
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to, using @rpdev's source address.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline
+int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+{
+	u32 src = rpdev->src;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @rpdev: the rpmsg channel
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline
+int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+							void *data, int len)
+{
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @rpdev: the rpmsg channel
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @rpdev channel.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to, using @rpdev's source and destination addresses.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline
+int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
+{
+	u32 src = rpdev->src, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @rpdev: the rpmsg channel
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to, using @rpdev's source address.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline
+int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+{
+	u32 src = rpdev->src;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @rpdev: the rpmsg channel
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @rpdev
+ * channel belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+static inline
+int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+							void *data, int len)
+{
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+
+#endif /* _LINUX_RPMSG_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4032ec1..b602610 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -552,6 +552,18 @@ struct signal_struct {
 	int			group_stop_count;
 	unsigned int		flags; /* see SIGNAL_* flags below */
 
+	/*
+	 * PR_SET_CHILD_SUBREAPER marks a process, like a service
+	 * manager, to re-parent orphan (double-forking) child processes
+	 * to this process instead of 'init'. The service manager is
+	 * able to receive SIGCHLD signals and is able to investigate
+	 * the process until it calls wait(). All children of this
+	 * process will inherit a flag if they should look for a
+	 * child_subreaper process at exit.
+	 */
+	unsigned int		is_child_subreaper:1;
+	unsigned int		has_child_subreaper:1;
+
 	/* POSIX.1b Interval Timers */
 	struct list_head posix_timers;
 
@@ -1590,6 +1602,10 @@ struct task_struct {
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 	atomic_t ptrace_bp_refcnt;
 #endif
+#ifdef CONFIG_UPROBES
+	struct uprobe_task *utask;
+	int uprobes_srcu_id;
+#endif
 };
 
 /* Future-safe accessor for struct task_struct's cpus_allowed. */
@@ -2090,7 +2106,7 @@ extern struct task_struct *idle_task(int cpu);
  * is_idle_task - is the specified task an idle task?
  * @tsk: the task in question.
  */
-static inline bool is_idle_task(struct task_struct *p)
+static inline bool is_idle_task(const struct task_struct *p)
 {
 	return p->pid == 0;
 }
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index e4c711c..79ab255 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -48,6 +48,7 @@ extern struct file *shmem_file_setup(const char *name,
 					loff_t size, unsigned long flags);
 extern int shmem_zero_setup(struct vm_area_struct *);
 extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern void shmem_unlock_mapping(struct address_space *mapping);
 extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 					pgoff_t index, gfp_t gfp_mask);
 extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 95040cc..91784a4 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -357,14 +357,29 @@ extern bool pm_save_wakeup_count(unsigned int count);
 
 static inline void lock_system_sleep(void)
 {
-	freezer_do_not_count();
+	current->flags |= PF_FREEZER_SKIP;
 	mutex_lock(&pm_mutex);
 }
 
 static inline void unlock_system_sleep(void)
 {
+	/*
+	 * Don't use freezer_count() because we don't want the call to
+	 * try_to_freeze() here.
+	 *
+	 * Reason:
+	 * Fundamentally, we just don't need it, because freezing condition
+	 * doesn't come into effect until we release the pm_mutex lock,
+	 * since the freezer always works with pm_mutex held.
+	 *
+	 * More importantly, in the case of hibernation,
+	 * unlock_system_sleep() gets called in snapshot_read() and
+	 * snapshot_write() when the freezing condition is still in effect.
+	 * Which means, if we use try_to_freeze() here, it would make them
+	 * enter the refrigerator, thus causing hibernation to lockup.
+	 */
+	current->flags &= ~PF_FREEZER_SKIP;
 	mutex_unlock(&pm_mutex);
-	freezer_count();
 }
 
 #else /* !CONFIG_PM_SLEEP */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 06061a7..e901f3f 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -208,6 +208,8 @@ struct swap_list_t {
 extern unsigned long totalram_pages;
 extern unsigned long totalreserve_pages;
 extern unsigned long dirty_balance_reserve;
+extern int min_free_kbytes;
+extern int extra_free_kbytes;
 extern unsigned int nr_free_buffer_pages(void);
 extern unsigned int nr_free_pagecache_pages(void);
 
@@ -273,7 +275,7 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
 #endif
 
 extern int page_evictable(struct page *page, struct vm_area_struct *vma);
-extern void scan_mapping_unevictable_pages(struct address_space *);
+extern void check_move_unevictable_pages(struct page **, int nr_pages);
 
 extern unsigned long scan_unevictable_pages;
 extern int scan_unevictable_handler(struct ctl_table *, int,
@@ -362,6 +364,26 @@ static inline void put_swap_token(struct mm_struct *mm)
 		__put_swap_token(mm);
 }
 
+static inline bool has_active_swap_token(struct mm_struct *mm)
+{
+	return has_swap_token(mm) && atomic_read(&mm->active_swap_token);
+}
+
+static inline bool activate_swap_token(struct mm_struct *mm)
+{
+	if (has_swap_token(mm)) {
+		atomic_inc(&mm->active_swap_token);
+		return true;
+	}
+	return false;
+}
+
+static inline void deactivate_swap_token(struct mm_struct *mm, bool swap_token)
+{
+	if (swap_token)
+		atomic_dec(&mm->active_swap_token);
+}
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 extern void
 mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout);
@@ -487,6 +509,20 @@ static inline int has_swap_token(struct mm_struct *mm)
 	return 0;
 }
 
+static inline bool has_active_swap_token(struct mm_struct *mm)
+{
+	return false;
+}
+
+static inline bool activate_swap_token(struct mm_struct *mm)
+{
+	return false;
+}
+
+static inline void deactivate_swap_token(struct mm_struct *mm, bool swap_token)
+{
+}
+
 static inline void disable_swap_token(struct mem_cgroup *memcg)
 {
 }
diff --git a/include/linux/topology.h b/include/linux/topology.h
index e26db03..b480403 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -239,7 +239,7 @@ static inline int cpu_to_node(int cpu)
 #ifndef set_numa_node
 static inline void set_numa_node(int node)
 {
-	percpu_write(numa_node, node);
+	__this_cpu_write(numa_node, node);
 }
 #endif
 
@@ -274,7 +274,7 @@ DECLARE_PER_CPU(int, _numa_mem_);
 #ifndef set_numa_mem
 static inline void set_numa_mem(int node)
 {
-	percpu_write(_numa_mem_, node);
+	__this_cpu_write(_numa_mem_, node);
 }
 #endif
 
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
new file mode 100644
index 0000000..adaa8d3
--- /dev/null
+++ b/include/linux/uprobes.h
@@ -0,0 +1,171 @@
+#ifndef _LINUX_UPROBES_H
+#define _LINUX_UPROBES_H
+/*
+ * Userspace Probes (UProbes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2008-2011
+ * Authors:
+ *	Srikar Dronamraju
+ *	Jim Keniston
+ */
+
+#include <linux/errno.h>
+#include <linux/rbtree.h>
+
+struct vm_area_struct;
+struct mm_struct;
+#ifdef CONFIG_ARCH_SUPPORTS_UPROBES
+#include <asm/uprobes.h>
+#else
+
+typedef u8 uprobe_opcode_t;
+struct uprobe_arch_info {};
+struct uprobe_task_arch_info {};	/* arch specific task info */
+#define MAX_UINSN_BYTES 4
+#endif
+
+#define uprobe_opcode_sz sizeof(uprobe_opcode_t)
+
+/* flags that denote/change uprobes behaviour */
+/* Have a copy of original instruction */
+#define UPROBES_COPY_INSN	0x1
+/* Dont run handlers when first register/ last unregister in progress*/
+#define UPROBES_RUN_HANDLER	0x2
+/* Can skip singlestep */
+#define UPROBES_SKIP_SSTEP	0x4
+
+struct uprobe_consumer {
+	int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
+	/*
+	 * filter is optional; If a filter exists, handler is run
+	 * if and only if filter returns true.
+	 */
+	bool (*filter)(struct uprobe_consumer *self, struct task_struct *task);
+
+	struct uprobe_consumer *next;
+};
+
+struct uprobe {
+	struct rb_node		rb_node;	/* node in the rb tree */
+	atomic_t		ref;
+	struct rw_semaphore	consumer_rwsem;
+	struct list_head	pending_list;
+	struct uprobe_arch_info arch_info;
+	struct uprobe_consumer	*consumers;
+	struct inode		*inode;		/* Also hold a ref to inode */
+	loff_t			offset;
+	int			flags;
+	u8			insn[MAX_UINSN_BYTES];
+};
+
+enum uprobe_task_state {
+	UTASK_RUNNING,
+	UTASK_BP_HIT,
+	UTASK_SSTEP,
+	UTASK_SSTEP_ACK,
+	UTASK_SSTEP_TRAPPED,
+};
+
+/*
+ * uprobe_task: Metadata of a task while it singlesteps.
+ */
+struct uprobe_task {
+	unsigned long xol_vaddr;
+	unsigned long vaddr;
+
+	enum uprobe_task_state state;
+	struct uprobe_task_arch_info tskinfo;
+
+	struct uprobe *active_uprobe;
+};
+
+/*
+ * On a breakpoint hit, thread contests for a slot.  It free the
+ * slot after singlestep.  Only definite number of slots are
+ * allocated.
+ */
+
+struct uprobes_xol_area {
+	wait_queue_head_t wq;	/* if all slots are busy */
+	atomic_t slot_count;	/* currently in use slots */
+	unsigned long *bitmap;	/* 0 = free slot */
+	struct page *page;
+
+	/*
+	 * We keep the vma's vm_start rather than a pointer to the vma
+	 * itself.  The probed process or a naughty kernel module could make
+	 * the vma go away, and we must handle that reasonably gracefully.
+	 */
+	unsigned long vaddr;		/* Page(s) of instruction slots */
+};
+
+#ifdef CONFIG_UPROBES
+extern int __weak set_bkpt(struct mm_struct *mm, struct uprobe *uprobe,
+							unsigned long vaddr);
+extern int __weak set_orig_insn(struct mm_struct *mm, struct uprobe *uprobe,
+					unsigned long vaddr, bool verify);
+extern bool __weak is_bkpt_insn(uprobe_opcode_t *insn);
+extern int register_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer);
+extern void unregister_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer);
+extern void free_uprobe_utask(struct task_struct *tsk);
+extern void free_uprobes_xol_area(struct mm_struct *mm);
+extern int mmap_uprobe(struct vm_area_struct *vma);
+extern void munmap_uprobe(struct vm_area_struct *vma);
+extern unsigned long __weak get_uprobe_bkpt_addr(struct pt_regs *regs);
+extern int uprobe_post_notifier(struct pt_regs *regs);
+extern int uprobe_bkpt_notifier(struct pt_regs *regs);
+extern void uprobe_notify_resume(struct pt_regs *regs);
+extern bool uprobe_deny_signal(void);
+extern bool __weak can_skip_xol(struct pt_regs *regs, struct uprobe *u);
+#else /* CONFIG_UPROBES is not defined */
+static inline int register_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer)
+{
+	return -ENOSYS;
+}
+static inline void unregister_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer)
+{
+}
+static inline int mmap_uprobe(struct vm_area_struct *vma)
+{
+	return 0;
+}
+static inline void munmap_uprobe(struct vm_area_struct *vma)
+{
+}
+static inline void uprobe_notify_resume(struct pt_regs *regs)
+{
+}
+static inline bool uprobe_deny_signal(void)
+{
+	return false;
+}
+static inline unsigned long get_uprobe_bkpt_addr(struct pt_regs *regs)
+{
+	return 0;
+}
+static inline void free_uprobe_utask(struct task_struct *tsk)
+{
+}
+static inline void free_uprobes_xol_area(struct mm_struct *mm)
+{
+}
+#endif /* CONFIG_UPROBES */
+#endif	/* _LINUX_UPROBES_H */
diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h
index 85bb0bb..b37c521 100644
--- a/include/linux/virtio_ids.h
+++ b/include/linux/virtio_ids.h
@@ -34,6 +34,7 @@
 #define VIRTIO_ID_CONSOLE	3 /* virtio console */
 #define VIRTIO_ID_RNG		4 /* virtio ring */
 #define VIRTIO_ID_BALLOON	5 /* virtio balloon */
+#define VIRTIO_ID_RPMSG		7 /* virtio remote processor messaging */
 #define VIRTIO_ID_9P		9 /* 9p virtio console */
 
 #endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/linux/xshm/Kbuild b/include/linux/xshm/Kbuild
new file mode 100644
index 0000000..4315a21
--- /dev/null
+++ b/include/linux/xshm/Kbuild
@@ -0,0 +1 @@
+header-y += xshm_netlink.h
diff --git a/include/linux/xshm/xshm_dev.h b/include/linux/xshm/xshm_dev.h
new file mode 100644
index 0000000..231d6d1
--- /dev/null
+++ b/include/linux/xshm/xshm_dev.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef XSHM_DEV_H_
+#define XSHM_DEV_H_
+
+#include <linux/device.h>
+#include <linux/firmware.h>
+
+#define XSHM_NAMESZ 16
+#define XSHM_MAX_CHANNELS 7
+#define XSHM_PACKET_MODE 0x1
+#define XSHM_STREAM_MODE 0x2
+#define XSHM_LOOP_MODE	 0x4
+#define XSHM_PAIR_MODE	 0x8
+#define XSHM_MODE_MASK	 0x3
+
+/**
+ * struct xshm_udchannel - Unidirectional channel for xshm driver.
+ *
+ * @addr: Base address of the channel, address must be
+ *		  a kernel logical address.
+ * @buffers: The number of buffers in the channel.
+ * @ch_size: The size of data area for the channel in one direction.
+ * @xfer_bit: GENI/O bit used when sending data (write pointer move)
+ * @xfer_done_bit: GENI/O bit used to indicate avilable buffers
+ *	(read pointer move).
+ * @alignment: Alignment used in payload protocol.
+ * @mtu: Maxium Transfer Unit used for packet in a buffer (Packet mode).
+ * @packets: Maxium number of packets in a buffer (Packet mode).
+ * @state: State of the device 0 - Closed, 1 - Open
+ * @read: Specify the read index for a channel. In packed mode
+ *	this index will at any time refer to the next buffer available for read.
+ *	In stream mode, this will be the read index in the ring-buffer.
+ * @write: Specify the write index for a channel. In packed mode
+ *	this index will at any time refer to the next buffer available for
+ *	write. In stream mode, this will be the write index in the ring-buffer.
+ * @buf_size: In packet mode, this array contains the size of each buffer.
+ *	In stream mode this is unused.
+ *
+ * This external shared memory channel configuration is exported from the
+ * xshm device. It gives the xshm driver the necessary information for
+ * running the shared memory protocol between modem and host.
+ *
+ * Note that two instances of this configuration is needed in order to run a
+ * bi-directional channel.
+ */
+struct xshm_udchannel {
+	void *addr;
+	u32 buffers;
+	u32 ch_size;
+	u8 xfer_done_bit;
+	u8 xfer_bit;
+	u32 mtu;
+	u32 alignment;
+	u32 packets;
+	__le32 *state;
+	__le32 *read;
+	__le32 *write;
+	__le32 *buf_size;
+/* private: */
+	struct kobject kobj; /* kobj must be located at the end */
+};
+
+/**
+ * struct xshm_channel - Channel definition for xshm driver.
+ * @rx: Configuration for RX channel
+ * @tx: Configuration for TX channel
+ * @excl_group: Only channels with the same group ID can be open simultaneously.
+ * @mode: Configuring type of channel PACKET(1), STREAM(2)
+ * @name: Name of interface.
+ * @priority: Priority of the channel.
+ * @latency: Latency of the channel.
+ */
+struct xshm_channel {
+	struct xshm_udchannel rx, tx;
+	u32 excl_group;
+	u32 mode;
+	char name[XSHM_NAMESZ];
+	u32 priority;
+	u32 latency;
+};
+
+#define XSHM_OPEN   1
+#define XSHM_CLOSED 0
+
+enum xshm_dev_state {
+	XSHM_DEV_CLOSED = 0,
+	XSHM_DEV_OPENING,
+	XSHM_DEV_OPEN,
+	XSHM_DEV_ACTIVE,
+};
+
+/**
+ * struct xshm_dev - Device definition for xshm device.
+ *
+ * @dev: Reference to device
+ * @cfg: Configuration for the Channel
+ * @state: State of the device: Closed - No user space client is using it,
+ *	Open - Open but no payload queued, Active - Payload queued on device.
+ *
+ * @open: The driver calls open() when channel is taken into use.
+ *	This function will fail if channel configuration is inconsistent,
+ *	or upon resource conflicts with other channels.
+ *
+ * @open_cb: The device calls open_cb() when is ready for use.
+ *
+ * @close: Called by the driver when a channel is no longer in use.
+ *
+ * @close_cb: The device calls close_cb() to notify about remote side closure.
+ *
+ * @ipc_tx_release_cb: This callback is triggered by the modem when a
+ *	transmit operation has completed and the buffer can be reused.
+ *	This function must be set by the driver upon device registration.
+ *	The "more" flag is set if ipc_rx_cb() call is coming immediately
+ *	after this call to ipc_tx_release_cb().
+ *
+ * @ipc_rx_cb: The driver gets this callback when the modem sends a buffer
+ *	from the modem. The driver must call ipc_rx_release()
+ *	to make the buffer available again when the received buffer has been
+ *	processed.
+ *	This function pointer must be set by the driver upon device
+ *	registration.
+ *
+ * @ipc_rx_release: Called by the driver when a RX operation has completed
+ *	and that the rx-buffer is released.
+ *
+ * @ipc_tx: Called by the driver when a TX buffer shall be sent to the modem.
+ *
+ * @driver_data: pointer to driver specific data.
+ *
+ * When communicating between two systems (e.g. modem and host),
+ * external shared memory can bused (e.g. C2C or DPRAM).
+ *
+ * This structure is used by the xshm device representing the
+ * External Shared Memory.
+ *
+ * The this structure contains configuration data for the xshm device and
+ * functions pointers for IPC communication between Linux host and modem.
+ * The external shared memory protocol memory e.g. C2C or DPRAM
+ * together is a IPC mechanism for transporting small commands such as
+ * Mailbox or GENI/O.
+ *
+ * This data structure is initiated by the xshm device, except
+ * for the functions ipc_rx_cb() and ipc_tx_release_cb(). They must be set by
+ * the xshm-driver when device is registering.
+ */
+
+struct xshm_dev {
+	struct device dev;
+	struct xshm_channel cfg;
+	enum xshm_dev_state state;
+	int (*open)(struct xshm_dev *dev);
+	void (*close)(struct xshm_dev *dev);
+	int (*ipc_rx_release)(struct xshm_dev *dev, bool more);
+	int (*ipc_tx)(struct xshm_dev *dev);
+	int (*open_cb)(void *drv);
+	void (*close_cb)(void *drv);
+	int (*ipc_rx_cb)(void *drv);
+	int (*ipc_tx_release_cb)(void *drv);
+	void *driver_data;
+	/* private: */
+	struct list_head node;
+	void *priv;
+};
+
+/**
+ * xshm_driver - operations for a xshm I/O driver
+ * @driver: underlying device driver (populate name and owner).
+ * @mode: Type of channel for driver: PACKET(1), STREAM(2)
+ * @probe: the function to call when a device is found.  Returns 0 or -errno.
+ * @remove: the function when a device is removed.
+ */
+struct xshm_driver {
+	struct device_driver driver;
+	u32 mode;
+	int (*probe)(struct xshm_dev *dev);
+	void (*remove)(struct xshm_dev *dev);
+};
+
+/**
+ * xshm_register_driver() - Register an xshm driver.
+ * @driver: XSHM driver instance
+ */
+int xshm_register_driver(struct xshm_driver *driver);
+
+/**
+ * xshm_unregister_driver() - Unregister an xshm driver.
+ * @driver: XSHM driver instance
+ */
+void xshm_unregister_driver(struct xshm_driver *driver);
+
+/**
+ * xshm_register_device() - Register an xshm device.
+ * @dev: XSHM device instance
+ */
+int xshm_register_device(struct xshm_dev *dev);
+
+/**
+ * xshm_unregister_device() - Unregister an xshm device.
+ * @dev: XSHM device instance
+ */
+void xshm_unregister_device(struct xshm_dev *dev);
+
+/**
+ * xshm_foreach_dev - device iterator.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over xshm bus's list of devices, and call @fn for each,
+ * passing it @data.
+ */
+void xshm_foreach_dev(void fn(struct xshm_dev*, void *data), void *data);
+
+/**
+ * xshm_register_devices() - Register an array of xshm devices.
+ * @devs: XSHM devices to register
+ * @devices: Number of devices in array
+ */
+int xshm_register_devices(struct xshm_channel *channel[], int channels);
+
+/**
+ * xshm_reset() - XSHM unregister and remove all XSHM devices
+ */
+void xshm_reset(void);
+
+/**
+ * genio_ipc_ready_cb() - Callback for CAIF_READY notification.
+ */
+void genio_ipc_ready_cb(void);
+
+/**
+ * xshm_request_firmware() - Request firmware from user-space.
+ * @context: Context returned in cb() function.
+ * @img_name: Name of the firmware image to load.
+ * @fw_avilable: Callback function called when firmware is avilable.
+ */
+int xshm_request_firmware(void *context, struct module *mod,
+		const char *img_name,
+		void (*fw_avilable)(const struct firmware *fw, void *ctx));
+
+#endif
diff --git a/include/linux/xshm/xshm_netlink.h b/include/linux/xshm/xshm_netlink.h
new file mode 100644
index 0000000..e785ad2
--- /dev/null
+++ b/include/linux/xshm/xshm_netlink.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2011
+ * Author: Sjur Brændeland / sjur.brandeland@stericsson.com
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef XSHM_NL_H_
+#define XSHM_NL_H_
+
+#define XSHM_PROTO_VERSION 1
+#define XSHM_PROTO_SUB_VERSION 0
+#define XSHM_NETLINK_VERSION 1
+/**
+ * enum XSHM_COMMANDS - Attributes used for configuring XSHM device.
+ *
+ * @XSHM_C_ADD_STREAM_CHANNEL: Adds a Stream Channel.
+ * This will cause an instance of XSHM-CHR to be created.
+ * @XSHM_C_ADD_PACKET_CHANNEL: Adds a Packet Channel.
+ * This will cause an instance of CAIF-SHM to be created.
+ * @XSHM_C_COMMIT: formats and write Channel configuration data to
+ *	Shared Memory.
+ * @XSHM_C_SET_ADDR: Writes the TOC address to GENO register.
+ * @XSHM_C_REGISTER:  Initiates registration of the channel devices.
+ *	This will cause xshm - character devices or
+ *	CAIF network instances to be created.
+ * @XSHM_C_RESET:  Reset the configuration data and removes the
+ *	platform devices and their associated channel configuration.
+ *	ipc_ready and caif_ready is set to false.
+ *
+ * A normal sequence of events is: [XSHM_C_RESET], [XSHM_C_ADD_X_CHANNEL],
+ *	XSHM_C_COMMIT, XSHM_C_REGISTER, XSHM_C_SET_ADDR.
+ */
+enum XSHM_COMMANDS {
+	XSHM_C_ADD_STREAM_CHANNEL = 1,
+	XSHM_C_ADD_PACKET_CHANNEL,
+	XSHM_C_RESET,
+	XSHM_C_SET_ADDR,
+	XSHM_C_COMMIT,
+	XSHM_C_REGISTER,
+	__XSHM_C_VERIFY,
+	__XSHM_C_MAX
+};
+
+/**
+ * enum XSHM_ATTRIBUTES - Attributes used for configuring XSHM device.
+ * @XSHM_A_VERSION: Version of XSHM netlink protocol. Type NLA_U8
+ * @XSHM_A_SUB_VERSION: Sub-version of XSHM netlink protocol. Type NLA_U8
+ * @XSHM_A_NAME: Name of the channel, max 15 characters. Type NLA_NUL_STRING
+ * @XSHM_A_EXCL_GROUP: Devices may be part of a group. Devices from the
+ *	same group are allowed to be open simultaneously,
+ *	but devices from different groups cannot be opened
+ *	at the same time. Type NLA_U8.
+ * @XSHM_A_RX_CHANNEL: The RX direction attributes. Type NLA_NESTED.
+ *	Each channel may contain the attributes - XSHM_A_CHANNEL_SIZE,
+ *	XSHM_A_CHANNEL_BUFFERS, XSHM_A_ALIGNMENT, XSHM_A_MTU.
+ *
+ * @XSHM_A_TX_CHANNEL: The TX direction attributes. Type NLA_NESTED.
+ *
+ * @XSHM_A_CHANNEL_SIZE: Size of the data area for a channel. Specified
+ *	for RX, TX. Type NLA_U32,
+ * @XSHM_A_CHANNEL_BUFFERS: Numer of buffers for a packet channel.
+ *	This attribute is only used for packet channels.  Specified for RX, TX.
+ *	Type NLA_U32,
+ * @XSHM_A_ALIGNMENT: Alignment for each packet in a buffer. This attribute
+ *	 is only used for packet channels.  Specified for RX, TX.Type NLA_U8,
+ * @XSHM_A_MTU: Maximum Transfer Unit for packets in a buffer.
+ *	This is only appplicable for packet channels.
+ *	Specified for RX, TX.Type NLA_U16,
+ * @XSHM_A_PACKETS: Maximum number of packets in a buffer. Type NLA_U8
+ * @XSHM_A_PRIORITY: Priority of the channel, legal range is 0-7 where
+ *	0 is lowest priority. Type NLA_U8.
+ * @XSHM_A_LATENCY: Latency for channel, value:0 means low latency
+ *	 and low bandwidth,
+ *	 value 1 means high latency and high bandwidth. Type NLA_U8.
+ */
+enum XSHM_ATTRIBUTES {
+	__XSHM_A_FLAGS = 1,		/* Test flags: NLA_U32 */
+	XSHM_A_VERSION,
+	XSHM_A_SUB_VERSION,
+	XSHM_A_NAME,
+	XSHM_A_EXCL_GROUP,
+	XSHM_A_RX_CHANNEL,
+	XSHM_A_TX_CHANNEL,
+	XSHM_A_CHANNEL_SIZE,
+	XSHM_A_CHANNEL_BUFFERS,
+	XSHM_A_ALIGNMENT,
+	XSHM_A_MTU,
+	XSHM_A_PACKETS,
+	XSHM_A_PRIORITY,
+	XSHM_A_LATENCY,
+	__XSHM_A_MAX,
+};
+#define XSHM_A_MAX (__XSHM_A_MAX - 1)
+
+#endif /* XSHM_NL_H_ */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 2974c8b..06225d2 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -352,6 +352,9 @@ void __init mount_block_root(char *name, int flags)
 	const char *b = name;
 #endif
 
+	if (sys_access((const char __user *) "/root", 0) != 0)
+		sys_mkdir((const char __user *) "/root", 0700);
+
 	get_fs_names(fs_names);
 retry:
 	for (p = fs_names; *p; p += strlen(p)+1) {
diff --git a/ipc/compat.c b/ipc/compat.c
index 845a287..a6df704 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -27,6 +27,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/syscalls.h>
+#include <linux/ptrace.h>
 
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
@@ -117,6 +118,7 @@ extern int sem_ctls[];
 
 static inline int compat_ipc_parse_version(int *cmd)
 {
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 	int version = *cmd & IPC_64;
 
 	/* this is tricky: architectures that have support for the old
@@ -128,6 +130,10 @@ static inline int compat_ipc_parse_version(int *cmd)
 	*cmd &= ~IPC_64;
 #endif
 	return version;
+#else
+	/* With the asm-generic APIs, we always use the 64-bit versions. */
+	return IPC_64;
+#endif
 }
 
 static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
@@ -232,10 +238,9 @@ static inline int put_compat_semid_ds(struct semid64_ds *s,
 	return err;
 }
 
-long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+static long do_compat_semctl(int first, int second, int third, u32 pad)
 {
 	union semun fourth;
-	u32 pad;
 	int err, err2;
 	struct semid64_ds s64;
 	struct semid64_ds __user *up64;
@@ -243,10 +248,6 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 
 	memset(&s64, 0, sizeof(s64));
 
-	if (!uptr)
-		return -EINVAL;
-	if (get_user(pad, (u32 __user *) uptr))
-		return -EFAULT;
 	if ((third & (~IPC_64)) == SETVAL)
 		fourth.val = (int) pad;
 	else
@@ -305,6 +306,18 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
 	return err;
 }
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
+long compat_sys_semctl(int first, int second, int third, void __user *uptr)
+{
+	u32 pad;
+
+	if (!uptr)
+		return -EINVAL;
+	if (get_user(pad, (u32 __user *) uptr))
+		return -EFAULT;
+	return do_compat_semctl(first, second, third, pad);
+}
+
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 {
 	struct compat_msgbuf __user *up = uptr;
@@ -353,6 +366,37 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 out:
 	return err;
 }
+#else
+long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
+{
+	return do_compat_semctl(semid, semnum, cmd, arg);
+}
+
+long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
+		       size_t msgsz, int msgflg)
+{
+	compat_long_t mtype;
+
+	if (get_user(mtype, &msgp->mtype))
+		return -EFAULT;
+	return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
+}
+
+long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
+		       size_t msgsz, long msgtyp, int msgflg)
+{
+	long err, mtype;
+
+	err =  do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
+	if (err < 0)
+		goto out;
+
+	if (put_user(mtype, &msgp->mtype))
+		err = -EFAULT;
+ out:
+	return err;
+}
+#endif
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
 				     struct compat_msqid64_ds __user *up64)
@@ -470,6 +514,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
 	return err;
 }
 
+#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
 long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
 			void __user *uptr)
 {
@@ -485,6 +530,19 @@ long compat_sys_shmat(int first, int second, compat_uptr_t third, int version,
 	uaddr = compat_ptr(third);
 	return put_user(raddr, uaddr);
 }
+#else
+long compat_sys_shmat(int shmid, compat_uptr_t shmaddr, int shmflg)
+{
+	unsigned long ret;
+	long err;
+
+	err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret);
+	if (err)
+		return err;
+	force_successful_syscall_return();
+	return (long)ret;
+}
+#endif
 
 static inline int get_compat_shmid64_ds(struct shmid64_ds *s64,
 					struct compat_shmid64_ds __user *up64)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 9b7c8ab..86ee272 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -128,7 +128,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 
 	if (S_ISREG(mode)) {
 		struct mqueue_inode_info *info;
-		struct task_struct *p = current;
 		unsigned long mq_bytes, mq_msg_tblsz;
 
 		inode->i_fop = &mqueue_file_operations;
@@ -159,7 +158,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
 
 		spin_lock(&mq_lock);
 		if (u->mq_bytes + mq_bytes < u->mq_bytes ||
-		    u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) {
+		    u->mq_bytes + mq_bytes > rlimit(RLIMIT_MSGQUEUE)) {
 			spin_unlock(&mq_lock);
 			/* mqueue_evict_inode() releases info->messages */
 			ret = -EMFILE;
diff --git a/ipc/sem.c b/ipc/sem.c
index 5215a81..10386b8 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -61,8 +61,8 @@
  * - A woken up task may not even touch the semaphore array anymore, it may
  *   have been destroyed already by a semctl(RMID).
  * - The synchronizations between wake-ups due to a timeout/signal and a
- *   wake-up due to a completed semaphore operation is achieved by using an
- *   intermediate state (IN_WAKEUP).
+ *   wake-up due to a completed semaphore operation is achieved by using a
+ *   special wakeup scheme (queuewakeup_wait and support functions)
  * - UNDO values are stored in an array (one per process and per
  *   semaphore array, lazily allocated). For backwards compatibility, multiple
  *   modes for the UNDO variables are supported (per process, per thread)
@@ -90,6 +90,135 @@
 #include <asm/uaccess.h>
 #include "util.h"
 
+
+#ifdef CONFIG_PREEMPT_RT_BASE
+	#define SYSVSEM_COMPLETION 1
+#else
+	#define SYSVSEM_CUSTOM 1
+#endif
+
+#ifdef SYSVSEM_COMPLETION
+	/* Using a completion causes some overhead, but avoids a busy loop
+	 * that increases the worst case latency.
+	 */
+	struct queue_done {
+		struct completion done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* no preparation necessary */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		complete_all(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		init_completion(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		wait_for_completion(&qd->done);
+	}
+
+#elif defined(SYSVSEM_SPINLOCK)
+	/* Note: Spinlocks do not work because:
+	 * - lockdep complains [could be fixed]
+	 * - only 255 concurrent spin_lock() calls are permitted, then the
+	 *   preempt-counter overflows
+	 */
+#error SYSVSEM_SPINLOCK is a prove of concept, does not work.
+	struct queue_done {
+		spinlock_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		/* empty */
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(spin_is_locked(&qd->done));
+		spin_lock(&qd->done);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		spin_unlock(&qd->done);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		spin_lock_init(&qd->done);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		spin_unlock_wait(&qd->done);
+	}
+#else
+	struct queue_done {
+		atomic_t done;
+	};
+
+	static void queuewakeup_prepare(void)
+	{
+		preempt_disable();
+	}
+
+	static void queuewakeup_completed(void)
+	{
+		preempt_enable();
+	}
+
+	static void queuewakeup_block(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 1);
+		atomic_set(&qd->done, 2);
+	}
+
+	static void queuewakeup_handsoff(struct queue_done *qd)
+	{
+		BUG_ON(atomic_read(&qd->done) != 2);
+		smp_mb();
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_init(struct queue_done *qd)
+	{
+		atomic_set(&qd->done, 1);
+	}
+
+	static void queuewakeup_wait(struct queue_done *qd)
+	{
+		while (atomic_read(&qd->done) != 1)
+			cpu_relax();
+
+		smp_mb();
+	}
+#endif
+
+
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
 	int	semval;		/* current value */
@@ -108,6 +237,7 @@ struct sem_queue {
 	struct sembuf		*sops;	 /* array of pending operations */
 	int			nsops;	 /* number of operations */
 	int			alter;	 /* does *sops alter the array? */
+	struct queue_done	done;	 /* completion synchronization */
 };
 
 /* Each task has a list of undo requests. They are executed automatically
@@ -245,23 +375,27 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  * - queue.status is initialized to -EINTR before blocking.
  * - wakeup is performed by
  *	* unlinking the queue entry from sma->sem_pending
- *	* setting queue.status to IN_WAKEUP
- *	  This is the notification for the blocked thread that a
- *	  result value is imminent.
+ *	* setting queue.status to the actual result code
+ *	  This is the notification for the blocked thread that someone
+ *	  (usually: update_queue()) completed the semtimedop() operation.
  *	* call wake_up_process
- *	* set queue.status to the final value.
+ *	* queuewakeup_handsoff(&q->done);
  * - the previously blocked thread checks queue.status:
- *   	* if it's IN_WAKEUP, then it must wait until the value changes
- *   	* if it's not -EINTR, then the operation was completed by
- *   	  update_queue. semtimedop can return queue.status without
- *   	  performing any operation on the sem array.
- *   	* otherwise it must acquire the spinlock and check what's up.
+ *	* if it's not -EINTR, then someone completed the operation.
+ *	  First, queuewakeup_wait() must be called. Afterwards,
+ *	  semtimedop must return queue.status without performing any
+ *	  operation on the sem array.
+ *	  - otherwise it must acquire the spinlock and repeat the test
+ *	  - If it is still -EINTR, then no update_queue() completed the
+ *	    operation, thus semtimedop() can proceed normally.
  *
- * The two-stage algorithm is necessary to protect against the following
+ * queuewakeup_wait() is necessary to protect against the following
  * races:
  * - if queue.status is set after wake_up_process, then the woken up idle
  *   thread could race forward and try (and fail) to acquire sma->lock
- *   before update_queue had a chance to set queue.status
+ *   before update_queue had a chance to set queue.status.
+ *   More importantly, it would mean that wake_up_process must be done
+ *   while holding sma->lock, i.e. this would reduce the scalability.
  * - if queue.status is written before wake_up_process and if the
  *   blocked process is woken up by a signal between writing
  *   queue.status and the wake_up_process, then the woken up
@@ -271,7 +405,6 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
  *   (yes, this happened on s390 with sysv msg).
  *
  */
-#define IN_WAKEUP	1
 
 /**
  * newary - Create a new semaphore set
@@ -461,15 +594,11 @@ undo:
 static void wake_up_sem_queue_prepare(struct list_head *pt,
 				struct sem_queue *q, int error)
 {
-	if (list_empty(pt)) {
-		/*
-		 * Hold preempt off so that we don't get preempted and have the
-		 * wakee busy-wait until we're scheduled back on.
-		 */
-		preempt_disable();
-	}
-	q->status = IN_WAKEUP;
-	q->pid = error;
+	if (list_empty(pt))
+		queuewakeup_prepare();
+
+	queuewakeup_block(&q->done);
+	q->status = error;
 
 	list_add_tail(&q->simple_list, pt);
 }
@@ -480,8 +609,8 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
  *
  * Do the actual wake-up.
  * The function is called without any locks held, thus the semaphore array
- * could be destroyed already and the tasks can disappear as soon as the
- * status is set to the actual return code.
+ * could be destroyed already and the tasks can disappear as soon as
+ * queuewakeup_handsoff() is called.
  */
 static void wake_up_sem_queue_do(struct list_head *pt)
 {
@@ -491,12 +620,11 @@ static void wake_up_sem_queue_do(struct list_head *pt)
 	did_something = !list_empty(pt);
 	list_for_each_entry_safe(q, t, pt, simple_list) {
 		wake_up_process(q->sleeper);
-		/* q can disappear immediately after writing q->status. */
-		smp_wmb();
-		q->status = q->pid;
+		/* q can disappear immediately after completing q->done */
+		queuewakeup_handsoff(&q->done);
 	}
 	if (did_something)
-		preempt_enable();
+		queuewakeup_completed();
 }
 
 static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
@@ -1300,33 +1428,6 @@ out:
 	return un;
 }
 
-
-/**
- * get_queue_result - Retrieve the result code from sem_queue
- * @q: Pointer to queue structure
- *
- * Retrieve the return code from the pending queue. If IN_WAKEUP is found in
- * q->status, then we must loop until the value is replaced with the final
- * value: This may happen if a task is woken up by an unrelated event (e.g.
- * signal) and in parallel the task is woken up by another task because it got
- * the requested semaphores.
- *
- * The function can be called with or without holding the semaphore spinlock.
- */
-static int get_queue_result(struct sem_queue *q)
-{
-	int error;
-
-	error = q->status;
-	while (unlikely(error == IN_WAKEUP)) {
-		cpu_relax();
-		error = q->status;
-	}
-
-	return error;
-}
-
-
 SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 		unsigned, nsops, const struct timespec __user *, timeout)
 {
@@ -1472,6 +1573,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
 
 	queue.status = -EINTR;
 	queue.sleeper = current;
+	queuewakeup_init(&queue.done);
 
 sleep_again:
 	current->state = TASK_INTERRUPTIBLE;
@@ -1482,17 +1584,14 @@ sleep_again:
 	else
 		schedule();
 
-	error = get_queue_result(&queue);
+	error = queue.status;
 
 	if (error != -EINTR) {
 		/* fast path: update_queue already obtained all requested
-		 * resources.
-		 * Perform a smp_mb(): User space could assume that semop()
-		 * is a memory barrier: Without the mb(), the cpu could
-		 * speculatively read in user space stale data that was
-		 * overwritten by the previous owner of the semaphore.
+		 * resources. Just ensure that update_queue completed
+		 * it's access to &queue.
 		 */
-		smp_mb();
+		queuewakeup_wait(&queue.done);
 
 		goto out_free;
 	}
@@ -1502,23 +1601,16 @@ sleep_again:
 	/*
 	 * Wait until it's guaranteed that no wakeup_sem_queue_do() is ongoing.
 	 */
-	error = get_queue_result(&queue);
-
-	/*
-	 * Array removed? If yes, leave without sem_unlock().
-	 */
-	if (IS_ERR(sma)) {
-		goto out_free;
-	}
-
-
-	/*
-	 * If queue.status != -EINTR we are woken up by another process.
-	 * Leave without unlink_queue(), but with sem_unlock().
-	 */
-
+	error = queue.status;
 	if (error != -EINTR) {
-		goto out_unlock_free;
+		/* If there is a return code, then we can leave immediately. */
+		if (!IS_ERR(sma)) {
+			/* sem_lock() succeeded - then unlock */
+			sem_unlock(sma);
+		}
+		/* Except that we must wait for the hands-off */
+		queuewakeup_wait(&queue.done);
+		goto out_free;
 	}
 
 	/*
diff --git a/ipc/shm.c b/ipc/shm.c
index 02ecf2c..b76be5b 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -870,9 +870,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 	case SHM_LOCK:
 	case SHM_UNLOCK:
 	{
-		struct file *uninitialized_var(shm_file);
-
-		lru_add_drain_all();  /* drain pagevecs to lru lists */
+		struct file *shm_file;
 
 		shp = shm_lock_check(ns, shmid);
 		if (IS_ERR(shp)) {
@@ -895,22 +893,31 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 		err = security_shm_shmctl(shp, cmd);
 		if (err)
 			goto out_unlock;
-		
-		if(cmd==SHM_LOCK) {
+
+		shm_file = shp->shm_file;
+		if (is_file_hugepages(shm_file))
+			goto out_unlock;
+
+		if (cmd == SHM_LOCK) {
 			struct user_struct *user = current_user();
-			if (!is_file_hugepages(shp->shm_file)) {
-				err = shmem_lock(shp->shm_file, 1, user);
-				if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){
-					shp->shm_perm.mode |= SHM_LOCKED;
-					shp->mlock_user = user;
-				}
+			err = shmem_lock(shm_file, 1, user);
+			if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
+				shp->shm_perm.mode |= SHM_LOCKED;
+				shp->mlock_user = user;
 			}
-		} else if (!is_file_hugepages(shp->shm_file)) {
-			shmem_lock(shp->shm_file, 0, shp->mlock_user);
-			shp->shm_perm.mode &= ~SHM_LOCKED;
-			shp->mlock_user = NULL;
+			goto out_unlock;
 		}
+
+		/* SHM_UNLOCK */
+		if (!(shp->shm_perm.mode & SHM_LOCKED))
+			goto out_unlock;
+		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);
+		shmem_unlock_mapping(shm_file->f_mapping);
+		fput(shm_file);
 		goto out;
 	}
 	case IPC_RMID:
diff --git a/kernel/Makefile b/kernel/Makefile
index 2d9de86..f439b53 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,7 +10,7 @@ obj-y     = fork.o exec_domain.o panic.o printk.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
 	    notifier.o ksysfs.o cred.o \
-	    async.o range.o groups.o
+	    async.o range.o groups.o lglock.o
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace debug files and internal ftrace files
@@ -107,6 +107,7 @@ obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_UPROBES) += uprobes.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c
index 7d6fb40..d35cc2d 100644
--- a/kernel/debug/kdb/kdb_support.c
+++ b/kernel/debug/kdb/kdb_support.c
@@ -384,9 +384,9 @@ static int kdb_getphys(void *res, unsigned long addr, size_t size)
 	if (!pfn_valid(pfn))
 		return 1;
 	page = pfn_to_page(pfn);
-	vaddr = kmap_atomic(page, KM_KDB);
+	vaddr = kmap_atomic(page);
 	memcpy(res, vaddr + (addr & (PAGE_SIZE - 1)), size);
-	kunmap_atomic(vaddr, KM_KDB);
+	kunmap_atomic(vaddr);
 
 	return 0;
 }
diff --git a/kernel/exit.c b/kernel/exit.c
index 294b170..72d4479 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -686,11 +686,11 @@ static void exit_mm(struct task_struct * tsk)
 }
 
 /*
- * When we die, we re-parent all our children.
- * Try to give them to another thread in our thread
- * group, and if no such member exists, give it to
- * the child reaper process (ie "init") in our pid
- * space.
+ * When we die, we re-parent all our children, and try to:
+ * 1. give them to another thread in our thread group, if such a member exists
+ * 2. give it to the first ancestor process which prctl'd itself as a
+ *    child_subreaper for its children (like a service manager)
+ * 3. give it to the init process (PID 1) in our pid namespace
  */
 static struct task_struct *find_new_reaper(struct task_struct *father)
 	__releases(&tasklist_lock)
@@ -721,6 +721,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 		 * forget_original_parent() must move them somewhere.
 		 */
 		pid_ns->child_reaper = init_pid_ns.child_reaper;
+	} else if (father->signal->has_child_subreaper) {
+		struct task_struct *reaper;
+
+		/*
+		 * Find the first ancestor marked as child_subreaper.
+		 * Note that the code below checks same_thread_group(reaper,
+		 * pid_ns->child_reaper).  This is what we need to DTRT in a
+		 * PID namespace. However we still need the check above, see
+		 * http://marc.info/?l=linux-kernel&m=131385460420380
+		 */
+		for (reaper = father->real_parent;
+		     reaper != &init_task;
+		     reaper = reaper->real_parent) {
+			if (same_thread_group(reaper, pid_ns->child_reaper))
+				break;
+			if (!reaper->signal->is_child_subreaper)
+				continue;
+			thread = reaper;
+			do {
+				if (!(thread->flags & PF_EXITING))
+					return reaper;
+			} while_each_thread(reaper, thread);
+		}
 	}
 
 	return pid_ns->child_reaper;
diff --git a/kernel/fork.c b/kernel/fork.c
index 051f090..6382487 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -66,6 +66,7 @@
 #include <linux/user-return-notifier.h>
 #include <linux/oom.h>
 #include <linux/khugepaged.h>
+#include <linux/uprobes.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -419,6 +420,9 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
 
 		if (retval)
 			goto out;
+
+		if (file && mmap_uprobe(tmp))
+			goto out;
 	}
 	/* a new mm has just been created */
 	arch_dup_mmap(oldmm, mm);
@@ -510,6 +514,23 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
 	return NULL;
 }
 
+static void check_mm(struct mm_struct *mm)
+{
+	int i;
+
+	for (i = 0; i < NR_MM_COUNTERS; i++) {
+		long x = atomic_long_read(&mm->rss_stat.count[i]);
+
+		if (unlikely(x))
+			printk(KERN_ALERT "BUG: Bad rss-counter state "
+					  "mm:%p idx:%d val:%ld\n", mm, i, x);
+	}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	VM_BUG_ON(mm->pmd_huge_pte);
+#endif
+}
+
 /*
  * Allocate and initialize an mm_struct.
  */
@@ -537,9 +558,7 @@ void __mmdrop(struct mm_struct *mm)
 	mm_free_pgd(mm);
 	destroy_context(mm);
 	mmu_notifier_mm_destroy(mm);
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-	VM_BUG_ON(mm->pmd_huge_pte);
-#endif
+	check_mm(mm);
 	free_mm(mm);
 }
 EXPORT_SYMBOL_GPL(__mmdrop);
@@ -552,6 +571,7 @@ void mmput(struct mm_struct *mm)
 	might_sleep();
 
 	if (atomic_dec_and_test(&mm->mm_users)) {
+		free_uprobes_xol_area(mm);
 		exit_aio(mm);
 		ksm_exit(mm);
 		khugepaged_exit(mm); /* must run before exit_mmap */
@@ -680,6 +700,8 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
 		exit_pi_state_list(tsk);
 #endif
 
+	free_uprobe_utask(tsk);
+
 	/* Get rid of any cached register state */
 	deactivate_mm(tsk, mm);
 
@@ -732,10 +754,15 @@ struct mm_struct *dup_mm(struct task_struct *tsk)
 	/* Initializing for Swap token stuff */
 	mm->token_priority = 0;
 	mm->last_interval = 0;
+	atomic_set(&mm->active_swap_token, 0);
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	mm->pmd_huge_pte = NULL;
 #endif
+#ifdef CONFIG_UPROBES
+	atomic_set(&mm->mm_uprobes_count, 0);
+	mm->uprobes_xol_area = NULL;
+#endif
 
 	if (!mm_init(mm, tsk))
 		goto fail_nomem;
@@ -984,6 +1011,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 	sig->oom_score_adj = current->signal->oom_score_adj;
 	sig->oom_score_adj_min = current->signal->oom_score_adj_min;
 
+	sig->has_child_subreaper = current->signal->has_child_subreaper ||
+				   current->signal->is_child_subreaper;
+
 	mutex_init(&sig->cred_guard_mutex);
 
 	return 0;
@@ -1272,6 +1302,10 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 	INIT_LIST_HEAD(&p->pi_state_list);
 	p->pi_state_cache = NULL;
 #endif
+#ifdef CONFIG_UPROBES
+	p->utask = NULL;
+	p->uprobes_srcu_id = -1;
+#endif
 	/*
 	 * sigaltstack should be cleared when sharing the same VM
 	 */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index ae34bf5..a53fff9 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1568,6 +1568,14 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
 	if (rt_task(current))
 		slack = 0;
 
+	/*
+	 * Applications will often sleep(0) to indicate that they wish to
+	 * be scheduled. Special case that to avoid actually putting them
+	 * to sleep for the duration of the slack.
+	 */
+	if (rqtp->tv_sec == 0 && rqtp->tv_nsec == 0)
+		slack = 0;
+
 	hrtimer_init_on_stack(&t.timer, clockid, mode);
 	hrtimer_set_expires_range_ns(&t.timer, timespec_to_ktime(*rqtp), slack);
 	if (do_nanosleep(&t, mode))
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index f7c543a..4dbc9c9 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type)
 		return -EINVAL;
 
 	type &= IRQ_TYPE_SENSE_MASK;
-	if (type != IRQ_TYPE_NONE)
-		ret = __irq_set_trigger(desc, irq, type);
+	ret = __irq_set_trigger(desc, irq, type);
 	irq_put_desc_busunlock(desc, flags);
 	return ret;
 }
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a9a9dbe..93d3079 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1026,9 +1026,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		if (new->flags & IRQF_ONESHOT)
 			desc->istate |= IRQS_ONESHOT;
 
-		if (irq_settings_can_autoenable(desc))
+		if (irq_settings_can_autoenable(desc)) {
 			irq_startup(desc);
-		else
+			check_irq_resend(desc, irq);
+		} else
 			/* Undo nested disables: */
 			desc->depth = 1;
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 95dd721..29f5b65 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1077,6 +1077,7 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
 		/* Early boot.  kretprobe_table_locks not yet initialized. */
 		return;
 
+	INIT_HLIST_HEAD(&empty_rp);
 	hash = hash_ptr(tk, KPROBE_HASH_BITS);
 	head = &kretprobe_inst_table[hash];
 	kretprobe_table_lock(hash, &flags);
@@ -1085,7 +1086,6 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
 			recycle_rp_inst(ri, &empty_rp);
 	}
 	kretprobe_table_unlock(hash, &flags);
-	INIT_HLIST_HEAD(&empty_rp);
 	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
 		kfree(ri);
diff --git a/kernel/lglock.c b/kernel/lglock.c
new file mode 100644
index 0000000..c6e6f09
--- /dev/null
+++ b/kernel/lglock.c
@@ -0,0 +1,136 @@
+/* See include/linux/lglock.h for description */
+#include <linux/module.h>
+#include <linux/lglock.h>
+#include <linux/cpu.h>
+#include <linux/string.h>
+
+/* Note there is no uninit, so lglocks cannot be defined in
+ * modules (but it's fine to use them from there)
+ * Could be added though, just undo lg_lock_init
+ */
+
+void lg_lock_init(struct lglock *lg, char *name)
+{
+	int i;
+
+	LOCKDEP_INIT_MAP(&lg->lock_dep_map, name, &lg->lock_key, 0);
+
+	register_hotcpu_notifier(&lg->cpu_notifier);
+	get_online_cpus();
+	for_each_online_cpu (i)
+		cpu_set(i, lg->cpus);
+	put_online_cpus();
+}
+EXPORT_SYMBOL(lg_lock_init);
+
+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 = this_cpu_ptr(lg->lock);
+	arch_spin_lock(lock);
+}
+EXPORT_SYMBOL(lg_local_lock);
+
+void lg_local_unlock(struct lglock *lg)
+{
+	arch_spinlock_t *lock;
+	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock = this_cpu_ptr(lg->lock);
+	arch_spin_unlock(lock);
+	preempt_enable();
+}
+EXPORT_SYMBOL(lg_local_unlock);
+
+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 = per_cpu_ptr(lg->lock, cpu);
+	arch_spin_lock(lock);
+}
+EXPORT_SYMBOL(lg_local_lock_cpu);
+
+void lg_local_unlock_cpu(struct lglock *lg, int cpu)
+{
+	arch_spinlock_t *lock;
+	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	lock = per_cpu_ptr(lg->lock, cpu);
+	arch_spin_unlock(lock);
+	preempt_enable();
+}
+EXPORT_SYMBOL(lg_local_unlock_cpu);
+
+void lg_global_lock_online(struct lglock *lg)
+{
+	int i;
+	spin_lock(&lg->cpu_lock);
+	rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	for_each_cpu(i, &lg->cpus) {
+		arch_spinlock_t *lock;
+		lock = per_cpu_ptr(lg->lock, i);
+		arch_spin_lock(lock);
+	}
+}
+EXPORT_SYMBOL(lg_global_lock_online);
+
+void lg_global_unlock_online(struct lglock *lg)
+{
+	int i;
+	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	for_each_cpu(i, &lg->cpus) {
+		arch_spinlock_t *lock;
+		lock = per_cpu_ptr(lg->lock, i);
+		arch_spin_unlock(lock);
+	}
+	spin_unlock(&lg->cpu_lock);
+}
+EXPORT_SYMBOL(lg_global_unlock_online);
+
+void lg_global_lock(struct lglock *lg)
+{
+	int i;
+	preempt_disable();
+	rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_);
+	for_each_possible_cpu(i) {
+		arch_spinlock_t *lock;
+		lock = per_cpu_ptr(lg->lock, i);
+		arch_spin_lock(lock);
+	}
+}
+EXPORT_SYMBOL(lg_global_lock);
+
+void lg_global_unlock(struct lglock *lg)
+{
+	int i;
+	rwlock_release(&lg->lock_dep_map, 1, _RET_IP_);
+	for_each_possible_cpu(i) {
+		arch_spinlock_t *lock;
+		lock = per_cpu_ptr(lg->lock, i);
+		arch_spin_unlock(lock);
+	}
+	preempt_enable();
+}
+EXPORT_SYMBOL(lg_global_unlock);
+
+int lg_cpu_callback(struct notifier_block *nb,
+                              unsigned long action, void *hcpu)
+{
+	struct lglock *lglock = container_of(nb, struct lglock, cpu_notifier);
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_UP_PREPARE:
+		spin_lock(&lglock->cpu_lock);
+		cpu_set((unsigned long)hcpu, lglock->cpus);
+		spin_unlock(&lglock->cpu_lock);
+		break;
+	case CPU_UP_CANCELED: case CPU_DEAD:
+		spin_lock(&lglock->cpu_lock);
+		cpu_clear((unsigned long)hcpu, lglock->cpus);
+		spin_unlock(&lglock->cpu_lock);
+	}
+	return NOTIFY_OK;
+}
+EXPORT_SYMBOL(lg_cpu_callback);
+
diff --git a/kernel/pid.c b/kernel/pid.c
index ce8e00d..9f08dfa 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -543,12 +543,12 @@ struct pid *find_ge_pid(int nr, struct pid_namespace *ns)
  */
 void __init pidhash_init(void)
 {
-	int i, pidhash_size;
+	unsigned int i, pidhash_size;
 
 	pid_hash = alloc_large_system_hash("PID", sizeof(*pid_hash), 0, 18,
 					   HASH_EARLY | HASH_SMALL,
 					   &pidhash_shift, NULL, 4096);
-	pidhash_size = 1 << pidhash_shift;
+	pidhash_size = 1U << pidhash_shift;
 
 	for (i = 0; i < pidhash_size; i++)
 		INIT_HLIST_HEAD(&pid_hash[i]);
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index a896839..b78969a 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -191,6 +191,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 	return;
 }
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static int pid_ns_ctl_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp, loff_t *ppos)
 {
@@ -218,13 +219,16 @@ static struct ctl_table pid_ns_ctl_table[] = {
 	},
 	{ }
 };
-
 static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } };
+#endif /* CONFIG_CHECKPOINT_RESTORE */
 
 static __init int pid_namespaces_init(void)
 {
 	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
 	register_sysctl_paths(kern_path, pid_ns_ctl_table);
+#endif
 	return 0;
 }
 
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 1cf8890..3a564ac 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -812,7 +812,8 @@ unsigned int snapshot_additional_pages(struct zone *zone)
 	unsigned int res;
 
 	res = DIV_ROUND_UP(zone->spanned_pages, BM_BITS_PER_BLOCK);
-	res += DIV_ROUND_UP(res * sizeof(struct bm_block), PAGE_SIZE);
+	res += DIV_ROUND_UP(res * sizeof(struct bm_block),
+			    LINKED_PAGE_DATA_SIZE);
 	return 2 * res;
 }
 
@@ -999,20 +1000,20 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
 	s_page = pfn_to_page(src_pfn);
 	d_page = pfn_to_page(dst_pfn);
 	if (PageHighMem(s_page)) {
-		src = kmap_atomic(s_page, KM_USER0);
-		dst = kmap_atomic(d_page, KM_USER1);
+		src = kmap_atomic(s_page);
+		dst = kmap_atomic(d_page);
 		do_copy_page(dst, src);
-		kunmap_atomic(dst, KM_USER1);
-		kunmap_atomic(src, KM_USER0);
+		kunmap_atomic(dst);
+		kunmap_atomic(src);
 	} else {
 		if (PageHighMem(d_page)) {
 			/* Page pointed to by src may contain some kernel
 			 * data modified by kmap_atomic()
 			 */
 			safe_copy_page(buffer, s_page);
-			dst = kmap_atomic(d_page, KM_USER0);
+			dst = kmap_atomic(d_page);
 			copy_page(dst, buffer);
-			kunmap_atomic(dst, KM_USER0);
+			kunmap_atomic(dst);
 		} else {
 			safe_copy_page(page_address(d_page), s_page);
 		}
@@ -1727,9 +1728,9 @@ int snapshot_read_next(struct snapshot_handle *handle)
 			 */
 			void *kaddr;
 
-			kaddr = kmap_atomic(page, KM_USER0);
+			kaddr = kmap_atomic(page);
 			copy_page(buffer, kaddr);
-			kunmap_atomic(kaddr, KM_USER0);
+			kunmap_atomic(kaddr);
 			handle->buffer = buffer;
 		} else {
 			handle->buffer = page_address(page);
@@ -2013,9 +2014,9 @@ static void copy_last_highmem_page(void)
 	if (last_highmem_page) {
 		void *dst;
 
-		dst = kmap_atomic(last_highmem_page, KM_USER0);
+		dst = kmap_atomic(last_highmem_page);
 		copy_page(dst, buffer);
-		kunmap_atomic(dst, KM_USER0);
+		kunmap_atomic(dst);
 		last_highmem_page = NULL;
 	}
 }
@@ -2308,13 +2309,13 @@ swap_two_pages_data(struct page *p1, struct page *p2, void *buf)
 {
 	void *kaddr1, *kaddr2;
 
-	kaddr1 = kmap_atomic(p1, KM_USER0);
-	kaddr2 = kmap_atomic(p2, KM_USER1);
+	kaddr1 = kmap_atomic(p1);
+	kaddr2 = kmap_atomic(p2);
 	copy_page(buf, kaddr1);
 	copy_page(kaddr1, kaddr2);
 	copy_page(kaddr2, buf);
-	kunmap_atomic(kaddr2, KM_USER1);
-	kunmap_atomic(kaddr1, KM_USER0);
+	kunmap_atomic(kaddr2);
+	kunmap_atomic(kaddr1);
 }
 
 /**
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 88f17b8..a58ac28 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -56,8 +56,8 @@ static int nreaders = -1;	/* # reader threads, defaults to 2*ncpus */
 static int nfakewriters = 4;	/* # fake writer threads */
 static int stat_interval;	/* Interval between stats, in seconds. */
 				/*  Defaults to "only at end of test". */
-static int verbose;		/* Print more debug info. */
-static int test_no_idle_hz;	/* Test RCU's support for tickless idle CPUs. */
+static bool verbose;		/* Print more debug info. */
+static bool test_no_idle_hz;	/* Test RCU's 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). */
@@ -1399,7 +1399,7 @@ rcu_torture_shutdown(void *arg)
  * Execute random CPU-hotplug operations at the interval specified
  * by the onoff_interval.
  */
-static int
+static int __cpuinit
 rcu_torture_onoff(void *arg)
 {
 	int cpu;
@@ -1447,7 +1447,7 @@ rcu_torture_onoff(void *arg)
 	return 0;
 }
 
-static int
+static int __cpuinit
 rcu_torture_onoff_init(void)
 {
 	if (onoff_interval <= 0)
diff --git a/kernel/signal.c b/kernel/signal.c
index c73c428..412f0dc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2182,6 +2182,9 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
 	struct signal_struct *signal = current->signal;
 	int signr;
 
+	if (unlikely(uprobe_deny_signal()))
+		return 0;
+
 relock:
 	/*
 	 * We'll jump back here after any time we were stopped in TASK_STOPPED.
diff --git a/kernel/sys.c b/kernel/sys.c
index 4070153..29995d4 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1962,6 +1962,14 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 		case PR_SET_MM:
 			error = prctl_set_mm(arg2, arg3, arg4, arg5);
 			break;
+		case PR_SET_CHILD_SUBREAPER:
+			me->signal->is_child_subreaper = !!arg2;
+			error = 0;
+			break;
+		case PR_GET_CHILD_SUBREAPER:
+			error = put_user(me->signal->is_child_subreaper,
+					 (int __user *) arg2);
+			break;
 		default:
 			error = -EINVAL;
 			break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f487f25..a0d30d0 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -96,7 +96,6 @@ extern int suid_dumpable;
 extern char core_pattern[];
 extern unsigned int core_pipe_limit;
 extern int pid_max;
-extern int min_free_kbytes;
 extern int pid_max_min, pid_max_max;
 extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
@@ -1205,7 +1204,15 @@ static struct ctl_table vm_table[] = {
 		.data		= &min_free_kbytes,
 		.maxlen		= sizeof(min_free_kbytes),
 		.mode		= 0644,
-		.proc_handler	= min_free_kbytes_sysctl_handler,
+		.proc_handler	= free_kbytes_sysctl_handler,
+		.extra1		= &zero,
+	},
+	{
+		.procname	= "extra_free_kbytes",
+		.data		= &extra_free_kbytes,
+		.maxlen		= sizeof(extra_free_kbytes),
+		.mode		= 0644,
+		.proc_handler	= free_kbytes_sysctl_handler,
 		.extra1		= &zero,
 	},
 	{
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 7656642..5d30c55 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -483,6 +483,14 @@ void tick_nohz_idle_enter(void)
 	 * update of the idle time accounting in tick_nohz_start_idle().
 	 */
 	ts->inidle = 1;
+
+	/*
+	 * Update the idle state in the scheduler domain hierarchy
+	 * when tick_nohz_idle_enter() is called from the idle loop.
+	 * State will be updated to busy during the first busy tick after
+	 * exiting idle.
+	 */
+	set_cpu_sd_state_idle();
 	tick_nohz_stop_sched_tick(ts);
 
 	local_irq_enable();
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index cd31345..b001fb1 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -373,6 +373,7 @@ config KPROBE_EVENT
 	depends on HAVE_REGS_AND_STACK_ACCESS_API
 	bool "Enable kprobes-based dynamic events"
 	select TRACING
+	select PROBE_EVENTS
 	default y
 	help
 	  This allows the user to add tracing events (similar to tracepoints)
@@ -385,6 +386,25 @@ config KPROBE_EVENT
 	  This option is also required by perf-probe subcommand of perf tools.
 	  If you want to use perf tools, this option is strongly recommended.
 
+config UPROBE_EVENT
+	bool "Enable uprobes-based dynamic events"
+	depends on ARCH_SUPPORTS_UPROBES
+	depends on MMU
+	select UPROBES
+	select PROBE_EVENTS
+	select TRACING
+	default n
+	help
+	  This allows the user to add tracing events on top of userspace dynamic
+	  events (similar to tracepoints) on the fly via the traceevents interface.
+	  Those events can be inserted wherever uprobes can probe, and record
+	  various registers.
+	  This option is required if you plan to use perf-probe subcommand of perf
+	  tools on user space applications.
+
+config PROBE_EVENTS
+	def_bool n
+
 config DYNAMIC_FTRACE
 	bool "enable/disable ftrace tracepoints dynamically"
 	depends on FUNCTION_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 5f39a07..1734c03 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -61,5 +61,7 @@ endif
 ifeq ($(CONFIG_TRACING),y)
 obj-$(CONFIG_KGDB_KDB) += trace_kdb.o
 endif
+obj-$(CONFIG_PROBE_EVENTS) += trace_probe.o
+obj-$(CONFIG_UPROBE_EVENT) += trace_uprobe.o
 
 libftrace-y := ftrace.o
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index b93ecba..03a5818 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -97,6 +97,11 @@ struct kretprobe_trace_entry_head {
 	unsigned long		ret_ip;
 };
 
+struct uprobe_trace_entry_head {
+	struct trace_entry	ent;
+	unsigned long		ip;
+};
+
 /*
  * trace_flag_type is an enumeration that holds different
  * states when a trace occurs. These are:
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 00d527c..60384df 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -19,547 +19,15 @@
 
 #include <linux/module.h>
 #include <linux/uaccess.h>
-#include <linux/kprobes.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/smp.h>
-#include <linux/debugfs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ptrace.h>
-#include <linux/perf_event.h>
-#include <linux/stringify.h>
-#include <linux/limits.h>
-#include <asm/bitsperlong.h>
-
-#include "trace.h"
-#include "trace_output.h"
-
-#define MAX_TRACE_ARGS 128
-#define MAX_ARGSTR_LEN 63
-#define MAX_EVENT_NAME_LEN 64
-#define MAX_STRING_SIZE PATH_MAX
-#define KPROBE_EVENT_SYSTEM "kprobes"
-
-/* Reserved field names */
-#define FIELD_STRING_IP "__probe_ip"
-#define FIELD_STRING_RETIP "__probe_ret_ip"
-#define FIELD_STRING_FUNC "__probe_func"
-
-const char *reserved_field_names[] = {
-	"common_type",
-	"common_flags",
-	"common_preempt_count",
-	"common_pid",
-	"common_tgid",
-	FIELD_STRING_IP,
-	FIELD_STRING_RETIP,
-	FIELD_STRING_FUNC,
-};
-
-/* Printing function type */
-typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *,
-				 void *);
-#define PRINT_TYPE_FUNC_NAME(type)	print_type_##type
-#define PRINT_TYPE_FMT_NAME(type)	print_type_format_##type
-
-/* Printing  in basic type function template */
-#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast)			\
-static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s,	\
-						const char *name,	\
-						void *data, void *ent)\
-{									\
-	return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\
-}									\
-static const char PRINT_TYPE_FMT_NAME(type)[] = fmt;
-
-DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int)
-DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int)
-DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long)
-DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long)
-DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int)
-DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int)
-DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long)
-DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long)
-
-/* data_rloc: data relative location, compatible with u32 */
-#define make_data_rloc(len, roffs)	\
-	(((u32)(len) << 16) | ((u32)(roffs) & 0xffff))
-#define get_rloc_len(dl)	((u32)(dl) >> 16)
-#define get_rloc_offs(dl)	((u32)(dl) & 0xffff)
-
-static inline void *get_rloc_data(u32 *dl)
-{
-	return (u8 *)dl + get_rloc_offs(*dl);
-}
-
-/* For data_loc conversion */
-static inline void *get_loc_data(u32 *dl, void *ent)
-{
-	return (u8 *)ent + get_rloc_offs(*dl);
-}
-
-/*
- * Convert data_rloc to data_loc:
- *  data_rloc stores the offset from data_rloc itself, but data_loc
- *  stores the offset from event entry.
- */
-#define convert_rloc_to_loc(dl, offs)	((u32)(dl) + (offs))
-
-/* For defining macros, define string/string_size types */
-typedef u32 string;
-typedef u32 string_size;
-
-/* Print type function for string type */
-static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s,
-						  const char *name,
-						  void *data, void *ent)
-{
-	int len = *(u32 *)data >> 16;
-
-	if (!len)
-		return trace_seq_printf(s, " %s=(fault)", name);
-	else
-		return trace_seq_printf(s, " %s=\"%s\"", name,
-					(const char *)get_loc_data(data, ent));
-}
-static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
-
-/* Data fetch function type */
-typedef	void (*fetch_func_t)(struct pt_regs *, void *, void *);
-
-struct fetch_param {
-	fetch_func_t	fn;
-	void *data;
-};
-
-static __kprobes void call_fetch(struct fetch_param *fprm,
-				 struct pt_regs *regs, void *dest)
-{
-	return fprm->fn(regs, fprm->data, dest);
-}
-
-#define FETCH_FUNC_NAME(method, type)	fetch_##method##_##type
-/*
- * Define macro for basic types - we don't need to define s* types, because
- * we have to care only about bitwidth at recording time.
- */
-#define DEFINE_BASIC_FETCH_FUNCS(method) \
-DEFINE_FETCH_##method(u8)		\
-DEFINE_FETCH_##method(u16)		\
-DEFINE_FETCH_##method(u32)		\
-DEFINE_FETCH_##method(u64)
-
-#define CHECK_FETCH_FUNCS(method, fn)			\
-	(((FETCH_FUNC_NAME(method, u8) == fn) ||	\
-	  (FETCH_FUNC_NAME(method, u16) == fn) ||	\
-	  (FETCH_FUNC_NAME(method, u32) == fn) ||	\
-	  (FETCH_FUNC_NAME(method, u64) == fn) ||	\
-	  (FETCH_FUNC_NAME(method, string) == fn) ||	\
-	  (FETCH_FUNC_NAME(method, string_size) == fn)) \
-	 && (fn != NULL))
-
-/* Data fetch function templates */
-#define DEFINE_FETCH_reg(type)						\
-static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs,	\
-					void *offset, void *dest)	\
-{									\
-	*(type *)dest = (type)regs_get_register(regs,			\
-				(unsigned int)((unsigned long)offset));	\
-}
-DEFINE_BASIC_FETCH_FUNCS(reg)
-/* No string on the register */
-#define fetch_reg_string NULL
-#define fetch_reg_string_size NULL
-
-#define DEFINE_FETCH_stack(type)					\
-static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\
-					  void *offset, void *dest)	\
-{									\
-	*(type *)dest = (type)regs_get_kernel_stack_nth(regs,		\
-				(unsigned int)((unsigned long)offset));	\
-}
-DEFINE_BASIC_FETCH_FUNCS(stack)
-/* No string on the stack entry */
-#define fetch_stack_string NULL
-#define fetch_stack_string_size NULL
-
-#define DEFINE_FETCH_retval(type)					\
-static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\
-					  void *dummy, void *dest)	\
-{									\
-	*(type *)dest = (type)regs_return_value(regs);			\
-}
-DEFINE_BASIC_FETCH_FUNCS(retval)
-/* No string on the retval */
-#define fetch_retval_string NULL
-#define fetch_retval_string_size NULL
-
-#define DEFINE_FETCH_memory(type)					\
-static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\
-					  void *addr, void *dest)	\
-{									\
-	type retval;							\
-	if (probe_kernel_address(addr, retval))				\
-		*(type *)dest = 0;					\
-	else								\
-		*(type *)dest = retval;					\
-}
-DEFINE_BASIC_FETCH_FUNCS(memory)
-/*
- * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
- * length and relative data location.
- */
-static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs,
-						      void *addr, void *dest)
-{
-	long ret;
-	int maxlen = get_rloc_len(*(u32 *)dest);
-	u8 *dst = get_rloc_data(dest);
-	u8 *src = addr;
-	mm_segment_t old_fs = get_fs();
-	if (!maxlen)
-		return;
-	/*
-	 * Try to get string again, since the string can be changed while
-	 * probing.
-	 */
-	set_fs(KERNEL_DS);
-	pagefault_disable();
-	do
-		ret = __copy_from_user_inatomic(dst++, src++, 1);
-	while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen);
-	dst[-1] = '\0';
-	pagefault_enable();
-	set_fs(old_fs);
-
-	if (ret < 0) {	/* Failed to fetch string */
-		((u8 *)get_rloc_data(dest))[0] = '\0';
-		*(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest));
-	} else
-		*(u32 *)dest = make_data_rloc(src - (u8 *)addr,
-					      get_rloc_offs(*(u32 *)dest));
-}
-/* Return the length of string -- including null terminal byte */
-static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs,
-							void *addr, void *dest)
-{
-	int ret, len = 0;
-	u8 c;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	pagefault_disable();
-	do {
-		ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1);
-		len++;
-	} while (c && ret == 0 && len < MAX_STRING_SIZE);
-	pagefault_enable();
-	set_fs(old_fs);
-
-	if (ret < 0)	/* Failed to check the length */
-		*(u32 *)dest = 0;
-	else
-		*(u32 *)dest = len;
-}
-
-/* Memory fetching by symbol */
-struct symbol_cache {
-	char *symbol;
-	long offset;
-	unsigned long addr;
-};
-
-static unsigned long update_symbol_cache(struct symbol_cache *sc)
-{
-	sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol);
-	if (sc->addr)
-		sc->addr += sc->offset;
-	return sc->addr;
-}
-
-static void free_symbol_cache(struct symbol_cache *sc)
-{
-	kfree(sc->symbol);
-	kfree(sc);
-}
-
-static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset)
-{
-	struct symbol_cache *sc;
-
-	if (!sym || strlen(sym) == 0)
-		return NULL;
-	sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL);
-	if (!sc)
-		return NULL;
-
-	sc->symbol = kstrdup(sym, GFP_KERNEL);
-	if (!sc->symbol) {
-		kfree(sc);
-		return NULL;
-	}
-	sc->offset = offset;
 
-	update_symbol_cache(sc);
-	return sc;
-}
-
-#define DEFINE_FETCH_symbol(type)					\
-static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\
-					  void *data, void *dest)	\
-{									\
-	struct symbol_cache *sc = data;					\
-	if (sc->addr)							\
-		fetch_memory_##type(regs, (void *)sc->addr, dest);	\
-	else								\
-		*(type *)dest = 0;					\
-}
-DEFINE_BASIC_FETCH_FUNCS(symbol)
-DEFINE_FETCH_symbol(string)
-DEFINE_FETCH_symbol(string_size)
-
-/* Dereference memory access function */
-struct deref_fetch_param {
-	struct fetch_param orig;
-	long offset;
-};
-
-#define DEFINE_FETCH_deref(type)					\
-static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\
-					    void *data, void *dest)	\
-{									\
-	struct deref_fetch_param *dprm = data;				\
-	unsigned long addr;						\
-	call_fetch(&dprm->orig, regs, &addr);				\
-	if (addr) {							\
-		addr += dprm->offset;					\
-		fetch_memory_##type(regs, (void *)addr, dest);		\
-	} else								\
-		*(type *)dest = 0;					\
-}
-DEFINE_BASIC_FETCH_FUNCS(deref)
-DEFINE_FETCH_deref(string)
-DEFINE_FETCH_deref(string_size)
-
-static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data)
-{
-	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
-		update_deref_fetch_param(data->orig.data);
-	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
-		update_symbol_cache(data->orig.data);
-}
-
-static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
-{
-	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
-		free_deref_fetch_param(data->orig.data);
-	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
-		free_symbol_cache(data->orig.data);
-	kfree(data);
-}
-
-/* Bitfield fetch function */
-struct bitfield_fetch_param {
-	struct fetch_param orig;
-	unsigned char hi_shift;
-	unsigned char low_shift;
-};
+#include "trace_probe.h"
 
-#define DEFINE_FETCH_bitfield(type)					\
-static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\
-					    void *data, void *dest)	\
-{									\
-	struct bitfield_fetch_param *bprm = data;			\
-	type buf = 0;							\
-	call_fetch(&bprm->orig, regs, &buf);				\
-	if (buf) {							\
-		buf <<= bprm->hi_shift;					\
-		buf >>= bprm->low_shift;				\
-	}								\
-	*(type *)dest = buf;						\
-}
-DEFINE_BASIC_FETCH_FUNCS(bitfield)
-#define fetch_bitfield_string NULL
-#define fetch_bitfield_string_size NULL
-
-static __kprobes void
-update_bitfield_fetch_param(struct bitfield_fetch_param *data)
-{
-	/*
-	 * Don't check the bitfield itself, because this must be the
-	 * last fetch function.
-	 */
-	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
-		update_deref_fetch_param(data->orig.data);
-	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
-		update_symbol_cache(data->orig.data);
-}
-
-static __kprobes void
-free_bitfield_fetch_param(struct bitfield_fetch_param *data)
-{
-	/*
-	 * Don't check the bitfield itself, because this must be the
-	 * last fetch function.
-	 */
-	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
-		free_deref_fetch_param(data->orig.data);
-	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
-		free_symbol_cache(data->orig.data);
-	kfree(data);
-}
-
-/* Default (unsigned long) fetch type */
-#define __DEFAULT_FETCH_TYPE(t) u##t
-#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
-#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG)
-#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE)
-
-/* Fetch types */
-enum {
-	FETCH_MTD_reg = 0,
-	FETCH_MTD_stack,
-	FETCH_MTD_retval,
-	FETCH_MTD_memory,
-	FETCH_MTD_symbol,
-	FETCH_MTD_deref,
-	FETCH_MTD_bitfield,
-	FETCH_MTD_END,
-};
-
-#define ASSIGN_FETCH_FUNC(method, type)	\
-	[FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type)
-
-#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype)	\
-	{.name = _name,				\
-	 .size = _size,					\
-	 .is_signed = sign,				\
-	 .print = PRINT_TYPE_FUNC_NAME(ptype),		\
-	 .fmt = PRINT_TYPE_FMT_NAME(ptype),		\
-	 .fmttype = _fmttype,				\
-	 .fetch = {					\
-ASSIGN_FETCH_FUNC(reg, ftype),				\
-ASSIGN_FETCH_FUNC(stack, ftype),			\
-ASSIGN_FETCH_FUNC(retval, ftype),			\
-ASSIGN_FETCH_FUNC(memory, ftype),			\
-ASSIGN_FETCH_FUNC(symbol, ftype),			\
-ASSIGN_FETCH_FUNC(deref, ftype),			\
-ASSIGN_FETCH_FUNC(bitfield, ftype),			\
-	  }						\
-	}
-
-#define ASSIGN_FETCH_TYPE(ptype, ftype, sign)			\
-	__ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype)
-
-#define FETCH_TYPE_STRING 0
-#define FETCH_TYPE_STRSIZE 1
-
-/* Fetch type information table */
-static const struct fetch_type {
-	const char	*name;		/* Name of type */
-	size_t		size;		/* Byte size of type */
-	int		is_signed;	/* Signed flag */
-	print_type_func_t	print;	/* Print functions */
-	const char	*fmt;		/* Fromat string */
-	const char	*fmttype;	/* Name in format file */
-	/* Fetch functions */
-	fetch_func_t	fetch[FETCH_MTD_END];
-} fetch_type_table[] = {
-	/* Special types */
-	[FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string,
-					sizeof(u32), 1, "__data_loc char[]"),
-	[FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32,
-					string_size, sizeof(u32), 0, "u32"),
-	/* Basic types */
-	ASSIGN_FETCH_TYPE(u8,  u8,  0),
-	ASSIGN_FETCH_TYPE(u16, u16, 0),
-	ASSIGN_FETCH_TYPE(u32, u32, 0),
-	ASSIGN_FETCH_TYPE(u64, u64, 0),
-	ASSIGN_FETCH_TYPE(s8,  u8,  1),
-	ASSIGN_FETCH_TYPE(s16, u16, 1),
-	ASSIGN_FETCH_TYPE(s32, u32, 1),
-	ASSIGN_FETCH_TYPE(s64, u64, 1),
-};
-
-static const struct fetch_type *find_fetch_type(const char *type)
-{
-	int i;
-
-	if (!type)
-		type = DEFAULT_FETCH_TYPE_STR;
-
-	/* Special case: bitfield */
-	if (*type == 'b') {
-		unsigned long bs;
-		type = strchr(type, '/');
-		if (!type)
-			goto fail;
-		type++;
-		if (strict_strtoul(type, 0, &bs))
-			goto fail;
-		switch (bs) {
-		case 8:
-			return find_fetch_type("u8");
-		case 16:
-			return find_fetch_type("u16");
-		case 32:
-			return find_fetch_type("u32");
-		case 64:
-			return find_fetch_type("u64");
-		default:
-			goto fail;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++)
-		if (strcmp(type, fetch_type_table[i].name) == 0)
-			return &fetch_type_table[i];
-fail:
-	return NULL;
-}
-
-/* Special function : only accept unsigned long */
-static __kprobes void fetch_stack_address(struct pt_regs *regs,
-					  void *dummy, void *dest)
-{
-	*(unsigned long *)dest = kernel_stack_pointer(regs);
-}
-
-static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
-					    fetch_func_t orig_fn)
-{
-	int i;
-
-	if (type != &fetch_type_table[FETCH_TYPE_STRING])
-		return NULL;	/* Only string type needs size function */
-	for (i = 0; i < FETCH_MTD_END; i++)
-		if (type->fetch[i] == orig_fn)
-			return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i];
-
-	WARN_ON(1);	/* This should not happen */
-	return NULL;
-}
+#define KPROBE_EVENT_SYSTEM "kprobes"
 
 /**
  * Kprobe event core functions
  */
 
-struct probe_arg {
-	struct fetch_param	fetch;
-	struct fetch_param	fetch_size;
-	unsigned int		offset;	/* Offset from argument entry */
-	const char		*name;	/* Name of this argument */
-	const char		*comm;	/* Command of this argument */
-	const struct fetch_type	*type;	/* Type of this argument */
-};
-
-/* Flags for trace_probe */
-#define TP_FLAG_TRACE	1
-#define TP_FLAG_PROFILE	2
-#define TP_FLAG_REGISTERED 4
-
 struct trace_probe {
 	struct list_head	list;
 	struct kretprobe	rp;	/* Use rp.kp for kprobe use */
@@ -631,18 +99,6 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
 static int kretprobe_dispatcher(struct kretprobe_instance *ri,
 				struct pt_regs *regs);
 
-/* Check the name is good for event/group/fields */
-static int is_good_name(const char *name)
-{
-	if (!isalpha(*name) && *name != '_')
-		return 0;
-	while (*++name != '\0') {
-		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
-			return 0;
-	}
-	return 1;
-}
-
 /*
  * Allocate new trace_probe and initialize it (including kprobes).
  */
@@ -651,7 +107,7 @@ static struct trace_probe *alloc_trace_probe(const char *group,
 					     void *addr,
 					     const char *symbol,
 					     unsigned long offs,
-					     int nargs, int is_return)
+					     int nargs, bool is_return)
 {
 	struct trace_probe *tp;
 	int ret = -ENOMEM;
@@ -702,34 +158,12 @@ error:
 	return ERR_PTR(ret);
 }
 
-static void update_probe_arg(struct probe_arg *arg)
-{
-	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
-		update_bitfield_fetch_param(arg->fetch.data);
-	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
-		update_deref_fetch_param(arg->fetch.data);
-	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
-		update_symbol_cache(arg->fetch.data);
-}
-
-static void free_probe_arg(struct probe_arg *arg)
-{
-	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
-		free_bitfield_fetch_param(arg->fetch.data);
-	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
-		free_deref_fetch_param(arg->fetch.data);
-	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
-		free_symbol_cache(arg->fetch.data);
-	kfree(arg->name);
-	kfree(arg->comm);
-}
-
 static void free_trace_probe(struct trace_probe *tp)
 {
 	int i;
 
 	for (i = 0; i < tp->nr_args; i++)
-		free_probe_arg(&tp->args[i]);
+		traceprobe_free_probe_arg(&tp->args[i]);
 
 	kfree(tp->call.class->system);
 	kfree(tp->call.name);
@@ -787,7 +221,7 @@ static int __register_trace_probe(struct trace_probe *tp)
 		return -EINVAL;
 
 	for (i = 0; i < tp->nr_args; i++)
-		update_probe_arg(&tp->args[i]);
+		traceprobe_update_arg(&tp->args[i]);
 
 	/* Set/clear disabled flag according to tp->flag */
 	if (trace_probe_is_enabled(tp))
@@ -919,227 +353,6 @@ static struct notifier_block trace_probe_module_nb = {
 	.priority = 1	/* Invoked after kprobe module callback */
 };
 
-/* Split symbol and offset. */
-static int split_symbol_offset(char *symbol, unsigned long *offset)
-{
-	char *tmp;
-	int ret;
-
-	if (!offset)
-		return -EINVAL;
-
-	tmp = strchr(symbol, '+');
-	if (tmp) {
-		/* skip sign because strict_strtol doesn't accept '+' */
-		ret = strict_strtoul(tmp + 1, 0, offset);
-		if (ret)
-			return ret;
-		*tmp = '\0';
-	} else
-		*offset = 0;
-	return 0;
-}
-
-#define PARAM_MAX_ARGS 16
-#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
-
-static int parse_probe_vars(char *arg, const struct fetch_type *t,
-			    struct fetch_param *f, int is_return)
-{
-	int ret = 0;
-	unsigned long param;
-
-	if (strcmp(arg, "retval") == 0) {
-		if (is_return)
-			f->fn = t->fetch[FETCH_MTD_retval];
-		else
-			ret = -EINVAL;
-	} else if (strncmp(arg, "stack", 5) == 0) {
-		if (arg[5] == '\0') {
-			if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0)
-				f->fn = fetch_stack_address;
-			else
-				ret = -EINVAL;
-		} else if (isdigit(arg[5])) {
-			ret = strict_strtoul(arg + 5, 10, &param);
-			if (ret || param > PARAM_MAX_STACK)
-				ret = -EINVAL;
-			else {
-				f->fn = t->fetch[FETCH_MTD_stack];
-				f->data = (void *)param;
-			}
-		} else
-			ret = -EINVAL;
-	} else
-		ret = -EINVAL;
-	return ret;
-}
-
-/* Recursive argument parser */
-static int __parse_probe_arg(char *arg, const struct fetch_type *t,
-			     struct fetch_param *f, int is_return)
-{
-	int ret = 0;
-	unsigned long param;
-	long offset;
-	char *tmp;
-
-	switch (arg[0]) {
-	case '$':
-		ret = parse_probe_vars(arg + 1, t, f, is_return);
-		break;
-	case '%':	/* named register */
-		ret = regs_query_register_offset(arg + 1);
-		if (ret >= 0) {
-			f->fn = t->fetch[FETCH_MTD_reg];
-			f->data = (void *)(unsigned long)ret;
-			ret = 0;
-		}
-		break;
-	case '@':	/* memory or symbol */
-		if (isdigit(arg[1])) {
-			ret = strict_strtoul(arg + 1, 0, &param);
-			if (ret)
-				break;
-			f->fn = t->fetch[FETCH_MTD_memory];
-			f->data = (void *)param;
-		} else {
-			ret = split_symbol_offset(arg + 1, &offset);
-			if (ret)
-				break;
-			f->data = alloc_symbol_cache(arg + 1, offset);
-			if (f->data)
-				f->fn = t->fetch[FETCH_MTD_symbol];
-		}
-		break;
-	case '+':	/* deref memory */
-		arg++;	/* Skip '+', because strict_strtol() rejects it. */
-	case '-':
-		tmp = strchr(arg, '(');
-		if (!tmp)
-			break;
-		*tmp = '\0';
-		ret = strict_strtol(arg, 0, &offset);
-		if (ret)
-			break;
-		arg = tmp + 1;
-		tmp = strrchr(arg, ')');
-		if (tmp) {
-			struct deref_fetch_param *dprm;
-			const struct fetch_type *t2 = find_fetch_type(NULL);
-			*tmp = '\0';
-			dprm = kzalloc(sizeof(struct deref_fetch_param),
-				       GFP_KERNEL);
-			if (!dprm)
-				return -ENOMEM;
-			dprm->offset = offset;
-			ret = __parse_probe_arg(arg, t2, &dprm->orig,
-						is_return);
-			if (ret)
-				kfree(dprm);
-			else {
-				f->fn = t->fetch[FETCH_MTD_deref];
-				f->data = (void *)dprm;
-			}
-		}
-		break;
-	}
-	if (!ret && !f->fn) {	/* Parsed, but do not find fetch method */
-		pr_info("%s type has no corresponding fetch method.\n",
-			t->name);
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
-#define BYTES_TO_BITS(nb)	((BITS_PER_LONG * (nb)) / sizeof(long))
-
-/* Bitfield type needs to be parsed into a fetch function */
-static int __parse_bitfield_probe_arg(const char *bf,
-				      const struct fetch_type *t,
-				      struct fetch_param *f)
-{
-	struct bitfield_fetch_param *bprm;
-	unsigned long bw, bo;
-	char *tail;
-
-	if (*bf != 'b')
-		return 0;
-
-	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
-	if (!bprm)
-		return -ENOMEM;
-	bprm->orig = *f;
-	f->fn = t->fetch[FETCH_MTD_bitfield];
-	f->data = (void *)bprm;
-
-	bw = simple_strtoul(bf + 1, &tail, 0);	/* Use simple one */
-	if (bw == 0 || *tail != '@')
-		return -EINVAL;
-
-	bf = tail + 1;
-	bo = simple_strtoul(bf, &tail, 0);
-	if (tail == bf || *tail != '/')
-		return -EINVAL;
-
-	bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
-	bprm->low_shift = bprm->hi_shift + bo;
-	return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
-}
-
-/* String length checking wrapper */
-static int parse_probe_arg(char *arg, struct trace_probe *tp,
-			   struct probe_arg *parg, int is_return)
-{
-	const char *t;
-	int ret;
-
-	if (strlen(arg) > MAX_ARGSTR_LEN) {
-		pr_info("Argument is too long.: %s\n",  arg);
-		return -ENOSPC;
-	}
-	parg->comm = kstrdup(arg, GFP_KERNEL);
-	if (!parg->comm) {
-		pr_info("Failed to allocate memory for command '%s'.\n", arg);
-		return -ENOMEM;
-	}
-	t = strchr(parg->comm, ':');
-	if (t) {
-		arg[t - parg->comm] = '\0';
-		t++;
-	}
-	parg->type = find_fetch_type(t);
-	if (!parg->type) {
-		pr_info("Unsupported type: %s\n", t);
-		return -EINVAL;
-	}
-	parg->offset = tp->size;
-	tp->size += parg->type->size;
-	ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return);
-	if (ret >= 0 && t != NULL)
-		ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
-	if (ret >= 0) {
-		parg->fetch_size.fn = get_fetch_size_function(parg->type,
-							      parg->fetch.fn);
-		parg->fetch_size.data = parg->fetch.data;
-	}
-	return ret;
-}
-
-/* Return 1 if name is reserved or already used by another argument */
-static int conflict_field_name(const char *name,
-			       struct probe_arg *args, int narg)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
-		if (strcmp(reserved_field_names[i], name) == 0)
-			return 1;
-	for (i = 0; i < narg; i++)
-		if (strcmp(args[i].name, name) == 0)
-			return 1;
-	return 0;
-}
-
 static int create_trace_probe(int argc, char **argv)
 {
 	/*
@@ -1162,7 +375,7 @@ static int create_trace_probe(int argc, char **argv)
 	 */
 	struct trace_probe *tp;
 	int i, ret = 0;
-	int is_return = 0, is_delete = 0;
+	bool is_return = false, is_delete = false;
 	char *symbol = NULL, *event = NULL, *group = NULL;
 	char *arg;
 	unsigned long offset = 0;
@@ -1171,11 +384,11 @@ static int create_trace_probe(int argc, char **argv)
 
 	/* argc must be >= 1 */
 	if (argv[0][0] == 'p')
-		is_return = 0;
+		is_return = false;
 	else if (argv[0][0] == 'r')
-		is_return = 1;
+		is_return = true;
 	else if (argv[0][0] == '-')
-		is_delete = 1;
+		is_delete = true;
 	else {
 		pr_info("Probe definition must be started with 'p', 'r' or"
 			" '-'.\n");
@@ -1240,7 +453,7 @@ static int create_trace_probe(int argc, char **argv)
 		/* a symbol specified */
 		symbol = argv[1];
 		/* TODO: support .init module functions */
-		ret = split_symbol_offset(symbol, &offset);
+		ret = traceprobe_split_symbol_offset(symbol, &offset);
 		if (ret) {
 			pr_info("Failed to parse symbol.\n");
 			return ret;
@@ -1302,7 +515,8 @@ static int create_trace_probe(int argc, char **argv)
 			goto error;
 		}
 
-		if (conflict_field_name(tp->args[i].name, tp->args, i)) {
+		if (traceprobe_conflict_field_name(tp->args[i].name,
+							tp->args, i)) {
 			pr_info("Argument[%d] name '%s' conflicts with "
 				"another field.\n", i, argv[i]);
 			ret = -EINVAL;
@@ -1310,7 +524,8 @@ static int create_trace_probe(int argc, char **argv)
 		}
 
 		/* Parse fetch argument */
-		ret = parse_probe_arg(arg, tp, &tp->args[i], is_return);
+		ret = traceprobe_parse_probe_arg(arg, &tp->size,
+					&tp->args[i], is_return, true);
 		if (ret) {
 			pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
 			goto error;
@@ -1412,70 +627,11 @@ static int probes_open(struct inode *inode, struct file *file)
 	return seq_open(file, &probes_seq_op);
 }
 
-static int command_trace_probe(const char *buf)
-{
-	char **argv;
-	int argc = 0, ret = 0;
-
-	argv = argv_split(GFP_KERNEL, buf, &argc);
-	if (!argv)
-		return -ENOMEM;
-
-	if (argc)
-		ret = create_trace_probe(argc, argv);
-
-	argv_free(argv);
-	return ret;
-}
-
-#define WRITE_BUFSIZE 4096
-
 static ssize_t probes_write(struct file *file, const char __user *buffer,
 			    size_t count, loff_t *ppos)
 {
-	char *kbuf, *tmp;
-	int ret;
-	size_t done;
-	size_t size;
-
-	kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
-	if (!kbuf)
-		return -ENOMEM;
-
-	ret = done = 0;
-	while (done < count) {
-		size = count - done;
-		if (size >= WRITE_BUFSIZE)
-			size = WRITE_BUFSIZE - 1;
-		if (copy_from_user(kbuf, buffer + done, size)) {
-			ret = -EFAULT;
-			goto out;
-		}
-		kbuf[size] = '\0';
-		tmp = strchr(kbuf, '\n');
-		if (tmp) {
-			*tmp = '\0';
-			size = tmp - kbuf + 1;
-		} else if (done + size < count) {
-			pr_warning("Line length is too long: "
-				   "Should be less than %d.", WRITE_BUFSIZE);
-			ret = -EINVAL;
-			goto out;
-		}
-		done += size;
-		/* Remove comments */
-		tmp = strchr(kbuf, '#');
-		if (tmp)
-			*tmp = '\0';
-
-		ret = command_trace_probe(kbuf);
-		if (ret)
-			goto out;
-	}
-	ret = done;
-out:
-	kfree(kbuf);
-	return ret;
+	return traceprobe_probes_write(file, buffer, count, ppos,
+			create_trace_probe);
 }
 
 static const struct file_operations kprobe_events_ops = {
@@ -1711,16 +867,6 @@ partial:
 	return TRACE_TYPE_PARTIAL_LINE;
 }
 
-#undef DEFINE_FIELD
-#define DEFINE_FIELD(type, item, name, is_signed)			\
-	do {								\
-		ret = trace_define_field(event_call, #type, name,	\
-					 offsetof(typeof(field), item),	\
-					 sizeof(field.item), is_signed, \
-					 FILTER_OTHER);			\
-		if (ret)						\
-			return ret;					\
-	} while (0)
 
 static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
 {
@@ -2045,8 +1191,9 @@ static __init int kprobe_trace_self_tests_init(void)
 
 	pr_info("Testing kprobe tracing: ");
 
-	ret = command_trace_probe("p:testprobe kprobe_trace_selftest_target "
-				  "$stack $stack0 +0($stack)");
+	ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target "
+				  "$stack $stack0 +0($stack)",
+				  create_trace_probe);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error on probing function entry.\n");
 		warn++;
@@ -2060,8 +1207,8 @@ static __init int kprobe_trace_self_tests_init(void)
 			enable_trace_probe(tp, TP_FLAG_TRACE);
 	}
 
-	ret = command_trace_probe("r:testprobe2 kprobe_trace_selftest_target "
-				  "$retval");
+	ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
+				  "$retval", create_trace_probe);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error on probing function return.\n");
 		warn++;
@@ -2095,13 +1242,13 @@ static __init int kprobe_trace_self_tests_init(void)
 	} else
 		disable_trace_probe(tp, TP_FLAG_TRACE);
 
-	ret = command_trace_probe("-:testprobe");
+	ret = traceprobe_command("-:testprobe", create_trace_probe);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error on deleting a probe.\n");
 		warn++;
 	}
 
-	ret = command_trace_probe("-:testprobe2");
+	ret = traceprobe_command("-:testprobe2", create_trace_probe);
 	if (WARN_ON_ONCE(ret)) {
 		pr_warning("error on deleting a probe.\n");
 		warn++;
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
new file mode 100644
index 0000000..c0a98e6
--- /dev/null
+++ b/kernel/trace/trace_probe.c
@@ -0,0 +1,786 @@
+/*
+ * Common code for probe-based Dynamic events.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This code was copied from kernel/trace/trace_kprobe.c written by
+ * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Updates to make this generic:
+ * Copyright (C) IBM Corporation, 2010-2011
+ * Author:     Srikar Dronamraju
+ */
+
+#include "trace_probe.h"
+
+const char *reserved_field_names[] = {
+	"common_type",
+	"common_flags",
+	"common_preempt_count",
+	"common_pid",
+	"common_tgid",
+	FIELD_STRING_IP,
+	FIELD_STRING_RETIP,
+	FIELD_STRING_FUNC,
+};
+
+/* Printing function type */
+#define PRINT_TYPE_FUNC_NAME(type)	print_type_##type
+#define PRINT_TYPE_FMT_NAME(type)	print_type_format_##type
+
+/* Printing  in basic type function template */
+#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast)			\
+static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s,	\
+						const char *name,	\
+						void *data, void *ent)\
+{									\
+	return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\
+}									\
+static const char PRINT_TYPE_FMT_NAME(type)[] = fmt;
+
+DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long)
+DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long)
+
+static inline void *get_rloc_data(u32 *dl)
+{
+	return (u8 *)dl + get_rloc_offs(*dl);
+}
+
+/* For data_loc conversion */
+static inline void *get_loc_data(u32 *dl, void *ent)
+{
+	return (u8 *)ent + get_rloc_offs(*dl);
+}
+
+/* For defining macros, define string/string_size types */
+typedef u32 string;
+typedef u32 string_size;
+
+/* Print type function for string type */
+static __kprobes int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s,
+						  const char *name,
+						  void *data, void *ent)
+{
+	int len = *(u32 *)data >> 16;
+
+	if (!len)
+		return trace_seq_printf(s, " %s=(fault)", name);
+	else
+		return trace_seq_printf(s, " %s=\"%s\"", name,
+					(const char *)get_loc_data(data, ent));
+}
+
+static const char PRINT_TYPE_FMT_NAME(string)[] = "\\\"%s\\\"";
+
+#define FETCH_FUNC_NAME(method, type)	fetch_##method##_##type
+/*
+ * Define macro for basic types - we don't need to define s* types, because
+ * we have to care only about bitwidth at recording time.
+ */
+#define DEFINE_BASIC_FETCH_FUNCS(method) \
+DEFINE_FETCH_##method(u8)		\
+DEFINE_FETCH_##method(u16)		\
+DEFINE_FETCH_##method(u32)		\
+DEFINE_FETCH_##method(u64)
+
+#define CHECK_FETCH_FUNCS(method, fn)			\
+	(((FETCH_FUNC_NAME(method, u8) == fn) ||	\
+	  (FETCH_FUNC_NAME(method, u16) == fn) ||	\
+	  (FETCH_FUNC_NAME(method, u32) == fn) ||	\
+	  (FETCH_FUNC_NAME(method, u64) == fn) ||	\
+	  (FETCH_FUNC_NAME(method, string) == fn) ||	\
+	  (FETCH_FUNC_NAME(method, string_size) == fn)) \
+	 && (fn != NULL))
+
+/* Data fetch function templates */
+#define DEFINE_FETCH_reg(type)						\
+static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs,	\
+					void *offset, void *dest)	\
+{									\
+	*(type *)dest = (type)regs_get_register(regs,			\
+				(unsigned int)((unsigned long)offset));	\
+}
+DEFINE_BASIC_FETCH_FUNCS(reg)
+/* No string on the register */
+#define fetch_reg_string NULL
+#define fetch_reg_string_size NULL
+
+#define DEFINE_FETCH_stack(type)					\
+static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\
+					  void *offset, void *dest)	\
+{									\
+	*(type *)dest = (type)regs_get_kernel_stack_nth(regs,		\
+				(unsigned int)((unsigned long)offset));	\
+}
+DEFINE_BASIC_FETCH_FUNCS(stack)
+/* No string on the stack entry */
+#define fetch_stack_string NULL
+#define fetch_stack_string_size NULL
+
+#define DEFINE_FETCH_retval(type)					\
+static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\
+					  void *dummy, void *dest)	\
+{									\
+	*(type *)dest = (type)regs_return_value(regs);			\
+}
+DEFINE_BASIC_FETCH_FUNCS(retval)
+/* No string on the retval */
+#define fetch_retval_string NULL
+#define fetch_retval_string_size NULL
+
+#define DEFINE_FETCH_memory(type)					\
+static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\
+					  void *addr, void *dest)	\
+{									\
+	type retval;							\
+	if (probe_kernel_address(addr, retval))				\
+		*(type *)dest = 0;					\
+	else								\
+		*(type *)dest = retval;					\
+}
+DEFINE_BASIC_FETCH_FUNCS(memory)
+/*
+ * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
+ * length and relative data location.
+ */
+static __kprobes void FETCH_FUNC_NAME(memory, string)(struct pt_regs *regs,
+						      void *addr, void *dest)
+{
+	long ret;
+	int maxlen = get_rloc_len(*(u32 *)dest);
+	u8 *dst = get_rloc_data(dest);
+	u8 *src = addr;
+	mm_segment_t old_fs = get_fs();
+	if (!maxlen)
+		return;
+	/*
+	 * Try to get string again, since the string can be changed while
+	 * probing.
+	 */
+	set_fs(KERNEL_DS);
+	pagefault_disable();
+	do
+		ret = __copy_from_user_inatomic(dst++, src++, 1);
+	while (dst[-1] && ret == 0 && src - (u8 *)addr < maxlen);
+	dst[-1] = '\0';
+	pagefault_enable();
+	set_fs(old_fs);
+
+	if (ret < 0) {	/* Failed to fetch string */
+		((u8 *)get_rloc_data(dest))[0] = '\0';
+		*(u32 *)dest = make_data_rloc(0, get_rloc_offs(*(u32 *)dest));
+	} else
+		*(u32 *)dest = make_data_rloc(src - (u8 *)addr,
+					      get_rloc_offs(*(u32 *)dest));
+}
+
+/* Return the length of string -- including null terminal byte */
+static __kprobes void FETCH_FUNC_NAME(memory, string_size)(struct pt_regs *regs,
+							void *addr, void *dest)
+{
+	int ret, len = 0;
+	u8 c;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	pagefault_disable();
+	do {
+		ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1);
+		len++;
+	} while (c && ret == 0 && len < MAX_STRING_SIZE);
+	pagefault_enable();
+	set_fs(old_fs);
+
+	if (ret < 0)	/* Failed to check the length */
+		*(u32 *)dest = 0;
+	else
+		*(u32 *)dest = len;
+}
+
+/* Memory fetching by symbol */
+struct symbol_cache {
+	char *symbol;
+	long offset;
+	unsigned long addr;
+};
+
+static unsigned long update_symbol_cache(struct symbol_cache *sc)
+{
+	sc->addr = (unsigned long)kallsyms_lookup_name(sc->symbol);
+	if (sc->addr)
+		sc->addr += sc->offset;
+	return sc->addr;
+}
+
+static void free_symbol_cache(struct symbol_cache *sc)
+{
+	kfree(sc->symbol);
+	kfree(sc);
+}
+
+static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset)
+{
+	struct symbol_cache *sc;
+
+	if (!sym || strlen(sym) == 0)
+		return NULL;
+	sc = kzalloc(sizeof(struct symbol_cache), GFP_KERNEL);
+	if (!sc)
+		return NULL;
+
+	sc->symbol = kstrdup(sym, GFP_KERNEL);
+	if (!sc->symbol) {
+		kfree(sc);
+		return NULL;
+	}
+	sc->offset = offset;
+
+	update_symbol_cache(sc);
+	return sc;
+}
+
+#define DEFINE_FETCH_symbol(type)					\
+static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\
+					  void *data, void *dest)	\
+{									\
+	struct symbol_cache *sc = data;					\
+	if (sc->addr)							\
+		fetch_memory_##type(regs, (void *)sc->addr, dest);	\
+	else								\
+		*(type *)dest = 0;					\
+}
+DEFINE_BASIC_FETCH_FUNCS(symbol)
+DEFINE_FETCH_symbol(string)
+DEFINE_FETCH_symbol(string_size)
+
+/* Dereference memory access function */
+struct deref_fetch_param {
+	struct fetch_param orig;
+	long offset;
+};
+
+#define DEFINE_FETCH_deref(type)					\
+static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\
+					    void *data, void *dest)	\
+{									\
+	struct deref_fetch_param *dprm = data;				\
+	unsigned long addr;						\
+	call_fetch(&dprm->orig, regs, &addr);				\
+	if (addr) {							\
+		addr += dprm->offset;					\
+		fetch_memory_##type(regs, (void *)addr, dest);		\
+	} else								\
+		*(type *)dest = 0;					\
+}
+DEFINE_BASIC_FETCH_FUNCS(deref)
+DEFINE_FETCH_deref(string)
+DEFINE_FETCH_deref(string_size)
+
+static __kprobes void update_deref_fetch_param(struct deref_fetch_param *data)
+{
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		update_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		update_symbol_cache(data->orig.data);
+}
+
+static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
+{
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		free_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		free_symbol_cache(data->orig.data);
+	kfree(data);
+}
+
+/* Bitfield fetch function */
+struct bitfield_fetch_param {
+	struct fetch_param orig;
+	unsigned char hi_shift;
+	unsigned char low_shift;
+};
+
+#define DEFINE_FETCH_bitfield(type)					\
+static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\
+					    void *data, void *dest)	\
+{									\
+	struct bitfield_fetch_param *bprm = data;			\
+	type buf = 0;							\
+	call_fetch(&bprm->orig, regs, &buf);				\
+	if (buf) {							\
+		buf <<= bprm->hi_shift;					\
+		buf >>= bprm->low_shift;				\
+	}								\
+	*(type *)dest = buf;						\
+}
+
+DEFINE_BASIC_FETCH_FUNCS(bitfield)
+#define fetch_bitfield_string NULL
+#define fetch_bitfield_string_size NULL
+
+static __kprobes void
+update_bitfield_fetch_param(struct bitfield_fetch_param *data)
+{
+	/*
+	 * Don't check the bitfield itself, because this must be the
+	 * last fetch function.
+	 */
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		update_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		update_symbol_cache(data->orig.data);
+}
+
+static __kprobes void
+free_bitfield_fetch_param(struct bitfield_fetch_param *data)
+{
+	/*
+	 * Don't check the bitfield itself, because this must be the
+	 * last fetch function.
+	 */
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		free_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		free_symbol_cache(data->orig.data);
+	kfree(data);
+}
+
+/* Default (unsigned long) fetch type */
+#define __DEFAULT_FETCH_TYPE(t) u##t
+#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
+#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG)
+#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE)
+
+#define ASSIGN_FETCH_FUNC(method, type)	\
+	[FETCH_MTD_##method] = FETCH_FUNC_NAME(method, type)
+
+#define __ASSIGN_FETCH_TYPE(_name, ptype, ftype, _size, sign, _fmttype)	\
+	{.name = _name,				\
+	 .size = _size,					\
+	 .is_signed = sign,				\
+	 .print = PRINT_TYPE_FUNC_NAME(ptype),		\
+	 .fmt = PRINT_TYPE_FMT_NAME(ptype),		\
+	 .fmttype = _fmttype,				\
+	 .fetch = {					\
+ASSIGN_FETCH_FUNC(reg, ftype),				\
+ASSIGN_FETCH_FUNC(stack, ftype),			\
+ASSIGN_FETCH_FUNC(retval, ftype),			\
+ASSIGN_FETCH_FUNC(memory, ftype),			\
+ASSIGN_FETCH_FUNC(symbol, ftype),			\
+ASSIGN_FETCH_FUNC(deref, ftype),			\
+ASSIGN_FETCH_FUNC(bitfield, ftype),			\
+	  }						\
+	}
+
+#define ASSIGN_FETCH_TYPE(ptype, ftype, sign)			\
+	__ASSIGN_FETCH_TYPE(#ptype, ptype, ftype, sizeof(ftype), sign, #ptype)
+
+#define FETCH_TYPE_STRING 0
+#define FETCH_TYPE_STRSIZE 1
+
+/* Fetch type information table */
+static const struct fetch_type fetch_type_table[] = {
+	/* Special types */
+	[FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string,
+					sizeof(u32), 1, "__data_loc char[]"),
+	[FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32,
+					string_size, sizeof(u32), 0, "u32"),
+	/* Basic types */
+	ASSIGN_FETCH_TYPE(u8,  u8,  0),
+	ASSIGN_FETCH_TYPE(u16, u16, 0),
+	ASSIGN_FETCH_TYPE(u32, u32, 0),
+	ASSIGN_FETCH_TYPE(u64, u64, 0),
+	ASSIGN_FETCH_TYPE(s8,  u8,  1),
+	ASSIGN_FETCH_TYPE(s16, u16, 1),
+	ASSIGN_FETCH_TYPE(s32, u32, 1),
+	ASSIGN_FETCH_TYPE(s64, u64, 1),
+};
+
+static const struct fetch_type *find_fetch_type(const char *type)
+{
+	int i;
+
+	if (!type)
+		type = DEFAULT_FETCH_TYPE_STR;
+
+	/* Special case: bitfield */
+	if (*type == 'b') {
+		unsigned long bs;
+		type = strchr(type, '/');
+		if (!type)
+			goto fail;
+		type++;
+		if (strict_strtoul(type, 0, &bs))
+			goto fail;
+		switch (bs) {
+		case 8:
+			return find_fetch_type("u8");
+		case 16:
+			return find_fetch_type("u16");
+		case 32:
+			return find_fetch_type("u32");
+		case 64:
+			return find_fetch_type("u64");
+		default:
+			goto fail;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++)
+		if (strcmp(type, fetch_type_table[i].name) == 0)
+			return &fetch_type_table[i];
+fail:
+	return NULL;
+}
+
+/* Special function : only accept unsigned long */
+static __kprobes void fetch_stack_address(struct pt_regs *regs,
+					void *dummy, void *dest)
+{
+	*(unsigned long *)dest = kernel_stack_pointer(regs);
+}
+
+static fetch_func_t get_fetch_size_function(const struct fetch_type *type,
+					fetch_func_t orig_fn)
+{
+	int i;
+
+	if (type != &fetch_type_table[FETCH_TYPE_STRING])
+		return NULL;	/* Only string type needs size function */
+	for (i = 0; i < FETCH_MTD_END; i++)
+		if (type->fetch[i] == orig_fn)
+			return fetch_type_table[FETCH_TYPE_STRSIZE].fetch[i];
+
+	WARN_ON(1);	/* This should not happen */
+	return NULL;
+}
+
+/* Split symbol and offset. */
+int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset)
+{
+	char *tmp;
+	int ret;
+
+	if (!offset)
+		return -EINVAL;
+
+	tmp = strchr(symbol, '+');
+	if (tmp) {
+		/* skip sign because strict_strtol doesn't accept '+' */
+		ret = strict_strtoul(tmp + 1, 0, offset);
+		if (ret)
+			return ret;
+		*tmp = '\0';
+	} else
+		*offset = 0;
+	return 0;
+}
+
+#define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long))
+
+static int parse_probe_vars(char *arg, const struct fetch_type *t,
+			    struct fetch_param *f, bool is_return)
+{
+	int ret = 0;
+	unsigned long param;
+
+	if (strcmp(arg, "retval") == 0) {
+		if (is_return)
+			f->fn = t->fetch[FETCH_MTD_retval];
+		else
+			ret = -EINVAL;
+	} else if (strncmp(arg, "stack", 5) == 0) {
+		if (arg[5] == '\0') {
+			if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0)
+				f->fn = fetch_stack_address;
+			else
+				ret = -EINVAL;
+		} else if (isdigit(arg[5])) {
+			ret = strict_strtoul(arg + 5, 10, &param);
+			if (ret || param > PARAM_MAX_STACK)
+				ret = -EINVAL;
+			else {
+				f->fn = t->fetch[FETCH_MTD_stack];
+				f->data = (void *)param;
+			}
+		} else
+			ret = -EINVAL;
+	} else
+		ret = -EINVAL;
+	return ret;
+}
+
+/* Recursive argument parser */
+static int parse_probe_arg(char *arg, const struct fetch_type *t,
+		     struct fetch_param *f, bool is_return, bool is_kprobe)
+{
+	int ret = 0;
+	unsigned long param;
+	long offset;
+	char *tmp;
+
+	/* Until uprobe_events supports only reg arguments */
+	if (!is_kprobe && arg[0] != '%')
+		return -EINVAL;
+
+	switch (arg[0]) {
+	case '$':
+		ret = parse_probe_vars(arg + 1, t, f, is_return);
+		break;
+	case '%':	/* named register */
+		ret = regs_query_register_offset(arg + 1);
+		if (ret >= 0) {
+			f->fn = t->fetch[FETCH_MTD_reg];
+			f->data = (void *)(unsigned long)ret;
+			ret = 0;
+		}
+		break;
+	case '@':	/* memory or symbol */
+		if (isdigit(arg[1])) {
+			ret = strict_strtoul(arg + 1, 0, &param);
+			if (ret)
+				break;
+			f->fn = t->fetch[FETCH_MTD_memory];
+			f->data = (void *)param;
+		} else {
+			ret = traceprobe_split_symbol_offset(arg + 1, &offset);
+			if (ret)
+				break;
+			f->data = alloc_symbol_cache(arg + 1, offset);
+			if (f->data)
+				f->fn = t->fetch[FETCH_MTD_symbol];
+		}
+		break;
+	case '+':	/* deref memory */
+		arg++;	/* Skip '+', because strict_strtol() rejects it. */
+	case '-':
+		tmp = strchr(arg, '(');
+		if (!tmp)
+			break;
+		*tmp = '\0';
+		ret = strict_strtol(arg, 0, &offset);
+		if (ret)
+			break;
+		arg = tmp + 1;
+		tmp = strrchr(arg, ')');
+		if (tmp) {
+			struct deref_fetch_param *dprm;
+			const struct fetch_type *t2 = find_fetch_type(NULL);
+			*tmp = '\0';
+			dprm = kzalloc(sizeof(struct deref_fetch_param),
+				       GFP_KERNEL);
+			if (!dprm)
+				return -ENOMEM;
+			dprm->offset = offset;
+			ret = parse_probe_arg(arg, t2, &dprm->orig, is_return,
+							is_kprobe);
+			if (ret)
+				kfree(dprm);
+			else {
+				f->fn = t->fetch[FETCH_MTD_deref];
+				f->data = (void *)dprm;
+			}
+		}
+		break;
+	}
+	if (!ret && !f->fn) {	/* Parsed, but do not find fetch method */
+		pr_info("%s type has no corresponding fetch method.\n",
+			t->name);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+#define BYTES_TO_BITS(nb)	((BITS_PER_LONG * (nb)) / sizeof(long))
+
+/* Bitfield type needs to be parsed into a fetch function */
+static int __parse_bitfield_probe_arg(const char *bf,
+				      const struct fetch_type *t,
+				      struct fetch_param *f)
+{
+	struct bitfield_fetch_param *bprm;
+	unsigned long bw, bo;
+	char *tail;
+
+	if (*bf != 'b')
+		return 0;
+
+	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		return -ENOMEM;
+	bprm->orig = *f;
+	f->fn = t->fetch[FETCH_MTD_bitfield];
+	f->data = (void *)bprm;
+
+	bw = simple_strtoul(bf + 1, &tail, 0);	/* Use simple one */
+	if (bw == 0 || *tail != '@')
+		return -EINVAL;
+
+	bf = tail + 1;
+	bo = simple_strtoul(bf, &tail, 0);
+	if (tail == bf || *tail != '/')
+		return -EINVAL;
+
+	bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
+	bprm->low_shift = bprm->hi_shift + bo;
+	return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
+}
+
+/* String length checking wrapper */
+int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
+		struct probe_arg *parg, bool is_return, bool is_kprobe)
+{
+	const char *t;
+	int ret;
+
+	if (strlen(arg) > MAX_ARGSTR_LEN) {
+		pr_info("Argument is too long.: %s\n",  arg);
+		return -ENOSPC;
+	}
+	parg->comm = kstrdup(arg, GFP_KERNEL);
+	if (!parg->comm) {
+		pr_info("Failed to allocate memory for command '%s'.\n", arg);
+		return -ENOMEM;
+	}
+	t = strchr(parg->comm, ':');
+	if (t) {
+		arg[t - parg->comm] = '\0';
+		t++;
+	}
+	parg->type = find_fetch_type(t);
+	if (!parg->type) {
+		pr_info("Unsupported type: %s\n", t);
+		return -EINVAL;
+	}
+	parg->offset = *size;
+	*size += parg->type->size;
+	ret = parse_probe_arg(arg, parg->type, &parg->fetch, is_return,
+							is_kprobe);
+	if (ret >= 0 && t != NULL)
+		ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
+	if (ret >= 0) {
+		parg->fetch_size.fn = get_fetch_size_function(parg->type,
+							      parg->fetch.fn);
+		parg->fetch_size.data = parg->fetch.data;
+	}
+	return ret;
+}
+
+/* Return 1 if name is reserved or already used by another argument */
+int traceprobe_conflict_field_name(const char *name,
+			       struct probe_arg *args, int narg)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++)
+		if (strcmp(reserved_field_names[i], name) == 0)
+			return 1;
+	for (i = 0; i < narg; i++)
+		if (strcmp(args[i].name, name) == 0)
+			return 1;
+	return 0;
+}
+
+void traceprobe_update_arg(struct probe_arg *arg)
+{
+	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
+		update_bitfield_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
+		update_deref_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
+		update_symbol_cache(arg->fetch.data);
+}
+
+void traceprobe_free_probe_arg(struct probe_arg *arg)
+{
+	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
+		free_bitfield_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
+		free_deref_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
+		free_symbol_cache(arg->fetch.data);
+	kfree(arg->name);
+	kfree(arg->comm);
+}
+
+int traceprobe_command(const char *buf, int (*createfn)(int, char **))
+{
+	char **argv;
+	int argc = 0, ret = 0;
+
+	argv = argv_split(GFP_KERNEL, buf, &argc);
+	if (!argv)
+		return -ENOMEM;
+
+	if (argc)
+		ret = createfn(argc, argv);
+
+	argv_free(argv);
+	return ret;
+}
+
+#define WRITE_BUFSIZE 128
+
+ssize_t traceprobe_probes_write(struct file *file, const char __user *buffer,
+				size_t count, loff_t *ppos,
+				int (*createfn)(int, char **))
+{
+	char *kbuf, *tmp;
+	int ret = 0;
+	size_t done = 0;
+	size_t size;
+
+	kbuf = kmalloc(WRITE_BUFSIZE, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	while (done < count) {
+		size = count - done;
+		if (size >= WRITE_BUFSIZE)
+			size = WRITE_BUFSIZE - 1;
+		if (copy_from_user(kbuf, buffer + done, size)) {
+			ret = -EFAULT;
+			goto out;
+		}
+		kbuf[size] = '\0';
+		tmp = strchr(kbuf, '\n');
+		if (tmp) {
+			*tmp = '\0';
+			size = tmp - kbuf + 1;
+		} else if (done + size < count) {
+			pr_warning("Line length is too long: "
+				   "Should be less than %d.", WRITE_BUFSIZE);
+			ret = -EINVAL;
+			goto out;
+		}
+		done += size;
+		/* Remove comments */
+		tmp = strchr(kbuf, '#');
+		if (tmp)
+			*tmp = '\0';
+
+		ret = traceprobe_command(kbuf, createfn);
+		if (ret)
+			goto out;
+	}
+	ret = done;
+out:
+	kfree(kbuf);
+	return ret;
+}
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
new file mode 100644
index 0000000..31e635e
--- /dev/null
+++ b/kernel/trace/trace_probe.h
@@ -0,0 +1,162 @@
+/*
+ * Common header file for probe-based Dynamic events.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * This code was copied from kernel/trace/trace_kprobe.h written by
+ * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Updates to make this generic:
+ * Copyright (C) IBM Corporation, 2010-2011
+ * Author:     Srikar Dronamraju
+ */
+
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/debugfs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/ptrace.h>
+#include <linux/perf_event.h>
+#include <linux/kprobes.h>
+#include <linux/stringify.h>
+#include <linux/limits.h>
+#include <linux/uaccess.h>
+#include <asm/bitsperlong.h>
+
+#include "trace.h"
+#include "trace_output.h"
+
+#define MAX_TRACE_ARGS 128
+#define MAX_ARGSTR_LEN 63
+#define MAX_EVENT_NAME_LEN 64
+#define MAX_STRING_SIZE PATH_MAX
+
+/* Reserved field names */
+#define FIELD_STRING_IP "__probe_ip"
+#define FIELD_STRING_RETIP "__probe_ret_ip"
+#define FIELD_STRING_FUNC "__probe_func"
+
+#undef DEFINE_FIELD
+#define DEFINE_FIELD(type, item, name, is_signed)			\
+	do {								\
+		ret = trace_define_field(event_call, #type, name,	\
+					 offsetof(typeof(field), item),	\
+					 sizeof(field.item), is_signed, \
+					 FILTER_OTHER);			\
+		if (ret)						\
+			return ret;					\
+	} while (0)
+
+
+/* Flags for trace_probe */
+#define TP_FLAG_TRACE	1
+#define TP_FLAG_PROFILE	2
+#define TP_FLAG_REGISTERED 4
+#define TP_FLAG_UPROBE	8
+
+
+/* data_rloc: data relative location, compatible with u32 */
+#define make_data_rloc(len, roffs)	\
+	(((u32)(len) << 16) | ((u32)(roffs) & 0xffff))
+#define get_rloc_len(dl)	((u32)(dl) >> 16)
+#define get_rloc_offs(dl)	((u32)(dl) & 0xffff)
+
+/*
+ * Convert data_rloc to data_loc:
+ *  data_rloc stores the offset from data_rloc itself, but data_loc
+ *  stores the offset from event entry.
+ */
+#define convert_rloc_to_loc(dl, offs)	((u32)(dl) + (offs))
+
+/* Data fetch function type */
+typedef	void (*fetch_func_t)(struct pt_regs *, void *, void *);
+/* Printing function type */
+typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *,
+				 void *);
+
+/* Fetch types */
+enum {
+	FETCH_MTD_reg = 0,
+	FETCH_MTD_stack,
+	FETCH_MTD_retval,
+	FETCH_MTD_memory,
+	FETCH_MTD_symbol,
+	FETCH_MTD_deref,
+	FETCH_MTD_bitfield,
+	FETCH_MTD_END,
+};
+
+/* Fetch type information table */
+struct fetch_type {
+	const char	*name;		/* Name of type */
+	size_t		size;		/* Byte size of type */
+	int		is_signed;	/* Signed flag */
+	print_type_func_t	print;	/* Print functions */
+	const char	*fmt;		/* Fromat string */
+	const char	*fmttype;	/* Name in format file */
+	/* Fetch functions */
+	fetch_func_t	fetch[FETCH_MTD_END];
+};
+
+struct fetch_param {
+	fetch_func_t	fn;
+	void *data;
+};
+
+struct probe_arg {
+	struct fetch_param	fetch;
+	struct fetch_param	fetch_size;
+	unsigned int		offset;	/* Offset from argument entry */
+	const char		*name;	/* Name of this argument */
+	const char		*comm;	/* Command of this argument */
+	const struct fetch_type	*type;	/* Type of this argument */
+};
+
+static inline __kprobes void call_fetch(struct fetch_param *fprm,
+				 struct pt_regs *regs, void *dest)
+{
+	return fprm->fn(regs, fprm->data, dest);
+}
+
+/* Check the name is good for event/group/fields */
+static inline int is_good_name(const char *name)
+{
+	if (!isalpha(*name) && *name != '_')
+		return 0;
+	while (*++name != '\0') {
+		if (!isalpha(*name) && !isdigit(*name) && *name != '_')
+			return 0;
+	}
+	return 1;
+}
+
+extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size,
+		   struct probe_arg *parg, bool is_return, bool is_kprobe);
+
+extern int traceprobe_conflict_field_name(const char *name,
+			       struct probe_arg *args, int narg);
+
+extern void traceprobe_update_arg(struct probe_arg *arg);
+extern void traceprobe_free_probe_arg(struct probe_arg *arg);
+
+extern int traceprobe_split_symbol_offset(char *symbol, unsigned long *offset);
+
+extern ssize_t traceprobe_probes_write(struct file *file,
+		const char __user *buffer, size_t count, loff_t *ppos,
+		int (*createfn)(int, char**));
+
+extern int traceprobe_command(const char *buf, int (*createfn)(int, char**));
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
new file mode 100644
index 0000000..af29368
--- /dev/null
+++ b/kernel/trace/trace_uprobe.c
@@ -0,0 +1,768 @@
+/*
+ * uprobes-based tracing events
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Copyright (C) IBM Corporation, 2010
+ * Author:	Srikar Dronamraju
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/uprobes.h>
+#include <linux/namei.h>
+
+#include "trace_probe.h"
+
+#define UPROBE_EVENT_SYSTEM "uprobes"
+
+/**
+ * uprobe event core functions
+ */
+struct trace_uprobe;
+struct uprobe_trace_consumer {
+	struct uprobe_consumer cons;
+	struct trace_uprobe *tp;
+};
+
+struct trace_uprobe {
+	struct list_head	list;
+	struct ftrace_event_class	class;
+	struct ftrace_event_call	call;
+	struct uprobe_trace_consumer	*consumer;
+	struct inode		*inode;
+	char			*filename;
+	unsigned long		offset;
+	unsigned long		nhit;
+	unsigned int		flags;	/* For TP_FLAG_* */
+	ssize_t			size;		/* trace entry size */
+	unsigned int		nr_args;
+	struct probe_arg	args[];
+};
+
+#define SIZEOF_TRACE_UPROBE(n)			\
+	(offsetof(struct trace_uprobe, args) +	\
+	(sizeof(struct probe_arg) * (n)))
+
+static int register_uprobe_event(struct trace_uprobe *tp);
+static void unregister_uprobe_event(struct trace_uprobe *tp);
+
+static DEFINE_MUTEX(uprobe_lock);
+static LIST_HEAD(uprobe_list);
+
+static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
+
+/*
+ * Allocate new trace_uprobe and initialize it (including uprobes).
+ */
+static struct trace_uprobe *alloc_trace_uprobe(const char *group,
+				const char *event, int nargs)
+{
+	struct trace_uprobe *tp;
+
+	if (!event || !is_good_name(event))
+		return ERR_PTR(-EINVAL);
+
+	if (!group || !is_good_name(group))
+		return ERR_PTR(-EINVAL);
+
+	tp = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
+	if (!tp)
+		return ERR_PTR(-ENOMEM);
+
+	tp->call.class = &tp->class;
+	tp->call.name = kstrdup(event, GFP_KERNEL);
+	if (!tp->call.name)
+		goto error;
+
+	tp->class.system = kstrdup(group, GFP_KERNEL);
+	if (!tp->class.system)
+		goto error;
+
+	INIT_LIST_HEAD(&tp->list);
+	return tp;
+error:
+	kfree(tp->call.name);
+	kfree(tp);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void free_trace_uprobe(struct trace_uprobe *tp)
+{
+	int i;
+
+	for (i = 0; i < tp->nr_args; i++)
+		traceprobe_free_probe_arg(&tp->args[i]);
+
+	iput(tp->inode);
+	kfree(tp->call.class->system);
+	kfree(tp->call.name);
+	kfree(tp->filename);
+	kfree(tp);
+}
+
+static struct trace_uprobe *find_probe_event(const char *event,
+					const char *group)
+{
+	struct trace_uprobe *tp;
+
+	list_for_each_entry(tp, &uprobe_list, list)
+		if (strcmp(tp->call.name, event) == 0 &&
+		    strcmp(tp->call.class->system, group) == 0)
+			return tp;
+	return NULL;
+}
+
+/* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */
+static void unregister_trace_uprobe(struct trace_uprobe *tp)
+{
+	list_del(&tp->list);
+	unregister_uprobe_event(tp);
+	free_trace_uprobe(tp);
+}
+
+/* Register a trace_uprobe and probe_event */
+static int register_trace_uprobe(struct trace_uprobe *tp)
+{
+	struct trace_uprobe *old_tp;
+	int ret;
+
+	mutex_lock(&uprobe_lock);
+
+	/* register as an event */
+	old_tp = find_probe_event(tp->call.name, tp->call.class->system);
+	if (old_tp)
+		/* delete old event */
+		unregister_trace_uprobe(old_tp);
+
+	ret = register_uprobe_event(tp);
+	if (ret) {
+		pr_warning("Failed to register probe event(%d)\n", ret);
+		goto end;
+	}
+
+	list_add_tail(&tp->list, &uprobe_list);
+end:
+	mutex_unlock(&uprobe_lock);
+	return ret;
+}
+
+static int create_trace_uprobe(int argc, char **argv)
+{
+	/*
+	 * Argument syntax:
+	 *  - Add uprobe: p[:[GRP/]EVENT] VADDR@PID [%REG]
+	 *
+	 *  - Remove uprobe: -:[GRP/]EVENT
+	 */
+	struct path path;
+	struct inode *inode = NULL;
+	struct trace_uprobe *tp;
+	int i, ret = 0;
+	int is_delete = 0;
+	char *arg = NULL, *event = NULL, *group = NULL;
+	unsigned long offset;
+	char buf[MAX_EVENT_NAME_LEN];
+	char *filename;
+
+	/* argc must be >= 1 */
+	if (argv[0][0] == '-')
+		is_delete = 1;
+	else if (argv[0][0] != 'p') {
+		pr_info("Probe definition must be started with 'p', 'r' or"
+			" '-'.\n");
+		return -EINVAL;
+	}
+
+	if (argv[0][1] == ':') {
+		event = &argv[0][2];
+		if (strchr(event, '/')) {
+			group = event;
+			event = strchr(group, '/') + 1;
+			event[-1] = '\0';
+			if (strlen(group) == 0) {
+				pr_info("Group name is not specified\n");
+				return -EINVAL;
+			}
+		}
+		if (strlen(event) == 0) {
+			pr_info("Event name is not specified\n");
+			return -EINVAL;
+		}
+	}
+	if (!group)
+		group = UPROBE_EVENT_SYSTEM;
+
+	if (is_delete) {
+		if (!event) {
+			pr_info("Delete command needs an event name.\n");
+			return -EINVAL;
+		}
+		mutex_lock(&uprobe_lock);
+		tp = find_probe_event(event, group);
+		if (!tp) {
+			mutex_unlock(&uprobe_lock);
+			pr_info("Event %s/%s doesn't exist.\n", group, event);
+			return -ENOENT;
+		}
+		/* delete an event */
+		unregister_trace_uprobe(tp);
+		mutex_unlock(&uprobe_lock);
+		return 0;
+	}
+
+	if (argc < 2) {
+		pr_info("Probe point is not specified.\n");
+		return -EINVAL;
+	}
+	if (isdigit(argv[1][0])) {
+		pr_info("probe point must be have a filename.\n");
+		return -EINVAL;
+	}
+	arg = strchr(argv[1], ':');
+	if (!arg)
+		goto fail_address_parse;
+
+	*arg++ = '\0';
+	filename = argv[1];
+	ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+	if (ret)
+		goto fail_address_parse;
+
+	inode = igrab(path.dentry->d_inode);
+
+	ret = strict_strtoul(arg, 0, &offset);
+		if (ret)
+			goto fail_address_parse;
+
+	argc -= 2;
+	argv += 2;
+
+	/* setup a probe */
+	if (!event) {
+		char *tail = strrchr(filename, '/');
+		char *ptr;
+
+		ptr = kstrdup((tail ? tail + 1 : filename), GFP_KERNEL);
+		if (!ptr) {
+			ret = -ENOMEM;
+			goto fail_address_parse;
+		}
+
+		tail = ptr;
+		ptr = strpbrk(tail, ".-_");
+		if (ptr)
+			*ptr = '\0';
+
+		snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail,
+				offset);
+		event = buf;
+		kfree(tail);
+	}
+	tp = alloc_trace_uprobe(group, event, argc);
+	if (IS_ERR(tp)) {
+		pr_info("Failed to allocate trace_uprobe.(%d)\n",
+			(int)PTR_ERR(tp));
+		iput(inode);
+		return PTR_ERR(tp);
+	}
+	tp->offset = offset;
+	tp->inode = inode;
+	tp->filename = kstrdup(filename, GFP_KERNEL);
+	if (!tp->filename) {
+			pr_info("Failed to allocate filename.\n");
+			ret = -ENOMEM;
+			goto error;
+	}
+
+	/* parse arguments */
+	ret = 0;
+	for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
+		/* Increment count for freeing args in error case */
+		tp->nr_args++;
+
+		/* Parse argument name */
+		arg = strchr(argv[i], '=');
+		if (arg) {
+			*arg++ = '\0';
+			tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
+		} else {
+			arg = argv[i];
+			/* If argument name is omitted, set "argN" */
+			snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
+			tp->args[i].name = kstrdup(buf, GFP_KERNEL);
+		}
+
+		if (!tp->args[i].name) {
+			pr_info("Failed to allocate argument[%d] name.\n", i);
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		if (!is_good_name(tp->args[i].name)) {
+			pr_info("Invalid argument[%d] name: %s\n",
+				i, tp->args[i].name);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		if (traceprobe_conflict_field_name(tp->args[i].name,
+							tp->args, i)) {
+			pr_info("Argument[%d] name '%s' conflicts with "
+				"another field.\n", i, argv[i]);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		/* Parse fetch argument */
+		ret = traceprobe_parse_probe_arg(arg, &tp->size, &tp->args[i],
+								false, false);
+		if (ret) {
+			pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
+			goto error;
+		}
+	}
+
+	ret = register_trace_uprobe(tp);
+	if (ret)
+		goto error;
+	return 0;
+
+error:
+	free_trace_uprobe(tp);
+	return ret;
+
+fail_address_parse:
+	if (inode)
+		iput(inode);
+	pr_info("Failed to parse address.\n");
+	return ret;
+}
+
+static void cleanup_all_probes(void)
+{
+	struct trace_uprobe *tp;
+
+	mutex_lock(&uprobe_lock);
+	while (!list_empty(&uprobe_list)) {
+		tp = list_entry(uprobe_list.next, struct trace_uprobe, list);
+		unregister_trace_uprobe(tp);
+	}
+	mutex_unlock(&uprobe_lock);
+}
+
+/* Probes listing interfaces */
+static void *probes_seq_start(struct seq_file *m, loff_t *pos)
+{
+	mutex_lock(&uprobe_lock);
+	return seq_list_start(&uprobe_list, *pos);
+}
+
+static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	return seq_list_next(v, &uprobe_list, pos);
+}
+
+static void probes_seq_stop(struct seq_file *m, void *v)
+{
+	mutex_unlock(&uprobe_lock);
+}
+
+static int probes_seq_show(struct seq_file *m, void *v)
+{
+	struct trace_uprobe *tp = v;
+	int i;
+
+	seq_printf(m, "p:%s/%s", tp->call.class->system, tp->call.name);
+	seq_printf(m, " %s:0x%p", tp->filename, (void *)tp->offset);
+
+	for (i = 0; i < tp->nr_args; i++)
+		seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm);
+	seq_printf(m, "\n");
+	return 0;
+}
+
+static const struct seq_operations probes_seq_op = {
+	.start  = probes_seq_start,
+	.next   = probes_seq_next,
+	.stop   = probes_seq_stop,
+	.show   = probes_seq_show
+};
+
+static int probes_open(struct inode *inode, struct file *file)
+{
+	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
+		cleanup_all_probes();
+
+	return seq_open(file, &probes_seq_op);
+}
+
+static ssize_t probes_write(struct file *file, const char __user *buffer,
+			    size_t count, loff_t *ppos)
+{
+	return traceprobe_probes_write(file, buffer, count, ppos,
+			create_trace_uprobe);
+}
+
+static const struct file_operations uprobe_events_ops = {
+	.owner          = THIS_MODULE,
+	.open           = probes_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = seq_release,
+	.write		= probes_write,
+};
+
+/* Probes profiling interfaces */
+static int probes_profile_seq_show(struct seq_file *m, void *v)
+{
+	struct trace_uprobe *tp = v;
+
+	seq_printf(m, "  %s %-44s %15lu\n", tp->filename, tp->call.name,
+								tp->nhit);
+	return 0;
+}
+
+static const struct seq_operations profile_seq_op = {
+	.start  = probes_seq_start,
+	.next   = probes_seq_next,
+	.stop   = probes_seq_stop,
+	.show   = probes_profile_seq_show
+};
+
+static int profile_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &profile_seq_op);
+}
+
+static const struct file_operations uprobe_profile_ops = {
+	.owner          = THIS_MODULE,
+	.open           = profile_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = seq_release,
+};
+
+/* uprobe handler */
+static void uprobe_trace_func(struct trace_uprobe *tp, struct pt_regs *regs)
+{
+	struct uprobe_trace_entry_head *entry;
+	struct ring_buffer_event *event;
+	struct ring_buffer *buffer;
+	u8 *data;
+	int size, i, pc;
+	unsigned long irq_flags;
+	struct ftrace_event_call *call = &tp->call;
+
+	tp->nhit++;
+
+	local_save_flags(irq_flags);
+	pc = preempt_count();
+
+	size = sizeof(*entry) + tp->size;
+
+	event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
+						  size, irq_flags, pc);
+	if (!event)
+		return;
+
+	entry = ring_buffer_event_data(event);
+	entry->ip = get_uprobe_bkpt_addr(task_pt_regs(current));
+	data = (u8 *)&entry[1];
+	for (i = 0; i < tp->nr_args; i++)
+		call_fetch(&tp->args[i].fetch, regs,
+						data + tp->args[i].offset);
+
+	if (!filter_current_check_discard(buffer, call, entry, event))
+		trace_buffer_unlock_commit(buffer, event, irq_flags, pc);
+}
+
+/* Event entry printers */
+static enum print_line_t
+print_uprobe_event(struct trace_iterator *iter, int flags,
+		   struct trace_event *event)
+{
+	struct uprobe_trace_entry_head *field;
+	struct trace_seq *s = &iter->seq;
+	struct trace_uprobe *tp;
+	u8 *data;
+	int i;
+
+	field = (struct uprobe_trace_entry_head *)iter->ent;
+	tp = container_of(event, struct trace_uprobe, call.event);
+
+	if (!trace_seq_printf(s, "%s: (", tp->call.name))
+		goto partial;
+
+	if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
+		goto partial;
+
+	if (!trace_seq_puts(s, ")"))
+		goto partial;
+
+	data = (u8 *)&field[1];
+	for (i = 0; i < tp->nr_args; i++)
+		if (!tp->args[i].type->print(s, tp->args[i].name,
+					     data + tp->args[i].offset, field))
+			goto partial;
+
+	if (!trace_seq_puts(s, "\n"))
+		goto partial;
+
+	return TRACE_TYPE_HANDLED;
+partial:
+	return TRACE_TYPE_PARTIAL_LINE;
+}
+
+static int probe_event_enable(struct trace_uprobe *tp, int flag)
+{
+	struct uprobe_trace_consumer *utc;
+	int ret = 0;
+
+	if (!tp->inode || tp->consumer)
+		return -EINTR;
+
+	utc = kzalloc(sizeof(struct uprobe_trace_consumer), GFP_KERNEL);
+	if (!utc)
+		return -EINTR;
+
+	utc->cons.handler = uprobe_dispatcher;
+	utc->cons.filter = NULL;
+	ret = register_uprobe(tp->inode, tp->offset, &utc->cons);
+	if (ret) {
+		kfree(utc);
+		return ret;
+	}
+
+	tp->flags |= flag;
+	utc->tp = tp;
+	tp->consumer = utc;
+	return 0;
+}
+
+static void probe_event_disable(struct trace_uprobe *tp, int flag)
+{
+	if (!tp->inode || !tp->consumer)
+		return;
+
+	unregister_uprobe(tp->inode, tp->offset, &tp->consumer->cons);
+	tp->flags &= ~flag;
+	kfree(tp->consumer);
+	tp->consumer = NULL;
+}
+
+static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
+{
+	int ret, i;
+	struct uprobe_trace_entry_head field;
+	struct trace_uprobe *tp = (struct trace_uprobe *)event_call->data;
+
+	DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
+	/* Set argument names as fields */
+	for (i = 0; i < tp->nr_args; i++) {
+		ret = trace_define_field(event_call, tp->args[i].type->fmttype,
+					 tp->args[i].name,
+					 sizeof(field) + tp->args[i].offset,
+					 tp->args[i].type->size,
+					 tp->args[i].type->is_signed,
+					 FILTER_OTHER);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static int __set_print_fmt(struct trace_uprobe *tp, char *buf, int len)
+{
+	int i;
+	int pos = 0;
+
+	const char *fmt, *arg;
+
+	fmt = "(%lx)";
+	arg = "REC->" FIELD_STRING_IP;
+
+	/* When len=0, we just calculate the needed length */
+#define LEN_OR_ZERO (len ? len - pos : 0)
+
+	pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
+
+	for (i = 0; i < tp->nr_args; i++) {
+		pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
+				tp->args[i].name, tp->args[i].type->fmt);
+	}
+
+	pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
+
+	for (i = 0; i < tp->nr_args; i++) {
+		pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
+				tp->args[i].name);
+	}
+
+#undef LEN_OR_ZERO
+
+	/* return the length of print_fmt */
+	return pos;
+}
+
+static int set_print_fmt(struct trace_uprobe *tp)
+{
+	int len;
+	char *print_fmt;
+
+	/* First: called with 0 length to calculate the needed length */
+	len = __set_print_fmt(tp, NULL, 0);
+	print_fmt = kmalloc(len + 1, GFP_KERNEL);
+	if (!print_fmt)
+		return -ENOMEM;
+
+	/* Second: actually write the @print_fmt */
+	__set_print_fmt(tp, print_fmt, len + 1);
+	tp->call.print_fmt = print_fmt;
+
+	return 0;
+}
+
+#ifdef CONFIG_PERF_EVENTS
+
+/* uprobe profile handler */
+static void uprobe_perf_func(struct trace_uprobe *tp, struct pt_regs *regs)
+{
+	struct ftrace_event_call *call = &tp->call;
+	struct uprobe_trace_entry_head *entry;
+	struct hlist_head *head;
+	u8 *data;
+	int size, __size, i;
+	int rctx;
+
+	__size = sizeof(*entry) + tp->size;
+	size = ALIGN(__size + sizeof(u32), sizeof(u64));
+	size -= sizeof(u32);
+	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
+		     "profile buffer not large enough"))
+		return;
+
+	entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
+	if (!entry)
+		return;
+
+	entry->ip = get_uprobe_bkpt_addr(task_pt_regs(current));
+	data = (u8 *)&entry[1];
+	for (i = 0; i < tp->nr_args; i++)
+		call_fetch(&tp->args[i].fetch, regs,
+						data + tp->args[i].offset);
+
+	head = this_cpu_ptr(call->perf_events);
+	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, regs, head);
+}
+#endif	/* CONFIG_PERF_EVENTS */
+
+static
+int uprobe_register(struct ftrace_event_call *event, enum trace_reg type)
+{
+	switch (type) {
+	case TRACE_REG_REGISTER:
+		return probe_event_enable(event->data, TP_FLAG_TRACE);
+	case TRACE_REG_UNREGISTER:
+		probe_event_disable(event->data, TP_FLAG_TRACE);
+		return 0;
+
+#ifdef CONFIG_PERF_EVENTS
+	case TRACE_REG_PERF_REGISTER:
+		return probe_event_enable(event->data, TP_FLAG_PROFILE);
+	case TRACE_REG_PERF_UNREGISTER:
+		probe_event_disable(event->data, TP_FLAG_PROFILE);
+		return 0;
+#endif
+	}
+	return 0;
+}
+
+static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
+{
+	struct uprobe_trace_consumer *utc;
+	struct trace_uprobe *tp;
+
+	utc = container_of(con, struct uprobe_trace_consumer, cons);
+	tp = utc->tp;
+	if (!tp || tp->consumer != utc)
+		return 0;
+
+	if (tp->flags & TP_FLAG_TRACE)
+		uprobe_trace_func(tp, regs);
+#ifdef CONFIG_PERF_EVENTS
+	if (tp->flags & TP_FLAG_PROFILE)
+		uprobe_perf_func(tp, regs);
+#endif
+	return 0;
+}
+
+static struct trace_event_functions uprobe_funcs = {
+	.trace		= print_uprobe_event
+};
+
+static int register_uprobe_event(struct trace_uprobe *tp)
+{
+	struct ftrace_event_call *call = &tp->call;
+	int ret;
+
+	/* Initialize ftrace_event_call */
+	INIT_LIST_HEAD(&call->class->fields);
+	call->event.funcs = &uprobe_funcs;
+	call->class->define_fields = uprobe_event_define_fields;
+	if (set_print_fmt(tp) < 0)
+		return -ENOMEM;
+	ret = register_ftrace_event(&call->event);
+	if (!ret) {
+		kfree(call->print_fmt);
+		return -ENODEV;
+	}
+	call->flags = 0;
+	call->class->reg = uprobe_register;
+	call->data = tp;
+	ret = trace_add_event_call(call);
+	if (ret) {
+		pr_info("Failed to register uprobe event: %s\n", call->name);
+		kfree(call->print_fmt);
+		unregister_ftrace_event(&call->event);
+	}
+	return ret;
+}
+
+static void unregister_uprobe_event(struct trace_uprobe *tp)
+{
+	/* tp->event is unregistered in trace_remove_event_call() */
+	trace_remove_event_call(&tp->call);
+	kfree(tp->call.print_fmt);
+	tp->call.print_fmt = NULL;
+}
+
+/* Make a trace interface for controling probe points */
+static __init int init_uprobe_trace(void)
+{
+	struct dentry *d_tracer;
+
+	d_tracer = tracing_init_dentry();
+	if (!d_tracer)
+		return 0;
+
+	trace_create_file("uprobe_events", 0644, d_tracer,
+				    NULL, &uprobe_events_ops);
+	/* Profile interface */
+	trace_create_file("uprobe_profile", 0444, d_tracer,
+				    NULL, &uprobe_profile_ops);
+	return 0;
+}
+
+fs_initcall(init_uprobe_trace);
diff --git a/kernel/uprobes.c b/kernel/uprobes.c
new file mode 100644
index 0000000..21ce23c
--- /dev/null
+++ b/kernel/uprobes.c
@@ -0,0 +1,1546 @@
+/*
+ * Userspace Probes (UProbes)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation, 2008-2011
+ * Authors:
+ *	Srikar Dronamraju
+ *	Jim Keniston
+ */
+
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>	/* read_mapping_page */
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/rmap.h>		/* anon_vma_prepare */
+#include <linux/mmu_notifier.h>	/* set_pte_at_notify */
+#include <linux/swap.h>		/* try_to_free_swap */
+#include <linux/ptrace.h>	/* user_enable_single_step */
+#include <linux/kdebug.h>	/* notifier mechanism */
+#include <linux/uprobes.h>
+
+#define UINSNS_PER_PAGE	(PAGE_SIZE/UPROBES_XOL_SLOT_BYTES)
+#define MAX_UPROBES_XOL_SLOTS UINSNS_PER_PAGE
+
+static struct srcu_struct uprobes_srcu;
+static struct rb_root uprobes_tree = RB_ROOT;
+static DEFINE_SPINLOCK(uprobes_treelock);	/* serialize rbtree access */
+
+#define UPROBES_HASH_SZ	13
+/* serialize (un)register */
+static struct mutex uprobes_mutex[UPROBES_HASH_SZ];
+#define uprobes_hash(v)	(&uprobes_mutex[((unsigned long)(v)) %\
+						UPROBES_HASH_SZ])
+
+/* serialize uprobe->pending_list */
+static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
+#define uprobes_mmap_hash(v)	(&uprobes_mmap_mutex[((unsigned long)(v)) %\
+						UPROBES_HASH_SZ])
+
+/*
+ * uprobe_events allows us to skip the mmap_uprobe if there are no uprobe
+ * events active at this time.  Probably a fine grained per inode count is
+ * better?
+ */
+static atomic_t uprobe_events = ATOMIC_INIT(0);
+
+/*
+ * Maintain a temporary per vma info that can be used to search if a vma
+ * has already been handled. This structure is introduced since extending
+ * vm_area_struct wasnt recommended.
+ */
+struct vma_info {
+	struct list_head probe_list;
+	struct mm_struct *mm;
+	loff_t vaddr;
+};
+
+/*
+ * valid_vma: Verify if the specified vma is an executable vma
+ * Relax restrictions while unregistering: vm_flags might have
+ * changed after breakpoint was inserted.
+ *	- is_register: indicates if we are in register context.
+ *	- Return 1 if the specified virtual address is in an
+ *	  executable vma.
+ */
+static bool valid_vma(struct vm_area_struct *vma, bool is_register)
+{
+	if (!vma->vm_file)
+		return false;
+
+	if (!is_register)
+		return true;
+
+	if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) ==
+						(VM_READ|VM_EXEC))
+		return true;
+
+	return false;
+}
+
+static loff_t vma_address(struct vm_area_struct *vma, loff_t offset)
+{
+	loff_t vaddr;
+
+	vaddr = vma->vm_start + offset;
+	vaddr -= vma->vm_pgoff << PAGE_SHIFT;
+	return vaddr;
+}
+
+/**
+ * __replace_page - replace page in vma by new page.
+ * based on replace_page in mm/ksm.c
+ *
+ * @vma:      vma that holds the pte pointing to page
+ * @page:     the cowed page we are replacing by kpage
+ * @kpage:    the modified page we replace page by
+ *
+ * Returns 0 on success, -EFAULT on failure.
+ */
+static int __replace_page(struct vm_area_struct *vma, struct page *page,
+					struct page *kpage)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep;
+	spinlock_t *ptl;
+	unsigned long addr;
+	int err = -EFAULT;
+
+	addr = page_address_in_vma(page, vma);
+	if (addr == -EFAULT)
+		goto out;
+
+	pgd = pgd_offset(mm, addr);
+	if (!pgd_present(*pgd))
+		goto out;
+
+	pud = pud_offset(pgd, addr);
+	if (!pud_present(*pud))
+		goto out;
+
+	pmd = pmd_offset(pud, addr);
+	if (!pmd_present(*pmd))
+		goto out;
+
+	ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
+	if (!ptep)
+		goto out;
+
+	get_page(kpage);
+	page_add_new_anon_rmap(kpage, vma, addr);
+
+	flush_cache_page(vma, addr, pte_pfn(*ptep));
+	ptep_clear_flush(vma, addr, ptep);
+	set_pte_at_notify(mm, addr, ptep, mk_pte(kpage, vma->vm_page_prot));
+
+	page_remove_rmap(page);
+	if (!page_mapped(page))
+		try_to_free_swap(page);
+	put_page(page);
+	pte_unmap_unlock(ptep, ptl);
+	err = 0;
+
+out:
+	return err;
+}
+
+/**
+ * is_bkpt_insn - check if instruction is breakpoint instruction.
+ * @insn: instruction to be checked.
+ * Default implementation of is_bkpt_insn
+ * Returns true if @insn is a breakpoint instruction.
+ */
+bool __weak is_bkpt_insn(uprobe_opcode_t *insn)
+{
+	return (*insn == UPROBES_BKPT_INSN);
+}
+
+/*
+ * NOTE:
+ * Expect the breakpoint instruction to be the smallest size instruction for
+ * the architecture. If an arch has variable length instruction and the
+ * breakpoint instruction is not of the smallest length instruction
+ * supported by that architecture then we need to modify read_opcode /
+ * write_opcode accordingly. This would never be a problem for archs that
+ * have fixed length instructions.
+ */
+
+/*
+ * write_opcode - write the opcode at a given virtual address.
+ * @mm: the probed process address space.
+ * @uprobe: the breakpointing information.
+ * @vaddr: the virtual address to store the opcode.
+ * @opcode: opcode to be written at @vaddr.
+ *
+ * Called with mm->mmap_sem held (for read and with a reference to
+ * mm).
+ *
+ * For mm @mm, write the opcode at @vaddr.
+ * Return 0 (success) or a negative errno.
+ */
+static int write_opcode(struct mm_struct *mm, struct uprobe *uprobe,
+			unsigned long vaddr, uprobe_opcode_t opcode)
+{
+	struct page *old_page, *new_page;
+	struct address_space *mapping;
+	void *vaddr_old, *vaddr_new;
+	struct vm_area_struct *vma;
+	loff_t addr;
+	int ret;
+
+	/* Read the page with vaddr into memory */
+	ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+	if (ret <= 0)
+		return ret;
+	ret = -EINVAL;
+
+	/*
+	 * We are interested in text pages only. Our pages of interest
+	 * should be mapped for read and execute only. We desist from
+	 * adding probes in write mapped pages since the breakpoints
+	 * might end up in the file copy.
+	 */
+	if (!valid_vma(vma, is_bkpt_insn(&opcode)))
+		goto put_out;
+
+	mapping = uprobe->inode->i_mapping;
+	if (mapping != vma->vm_file->f_mapping)
+		goto put_out;
+
+	addr = vma_address(vma, uprobe->offset);
+	if (vaddr != (unsigned long)addr)
+		goto put_out;
+
+	ret = -ENOMEM;
+	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
+	if (!new_page)
+		goto put_out;
+
+	__SetPageUptodate(new_page);
+
+	/*
+	 * lock page will serialize against do_wp_page()'s
+	 * PageAnon() handling
+	 */
+	lock_page(old_page);
+	/* copy the page now that we've got it stable */
+	vaddr_old = kmap_atomic(old_page);
+	vaddr_new = kmap_atomic(new_page);
+
+	memcpy(vaddr_new, vaddr_old, PAGE_SIZE);
+	/* poke the new insn in, ASSUMES we don't cross page boundary */
+	vaddr &= ~PAGE_MASK;
+	BUG_ON(vaddr + uprobe_opcode_sz > PAGE_SIZE);
+	memcpy(vaddr_new + vaddr, &opcode, uprobe_opcode_sz);
+
+	kunmap_atomic(vaddr_new);
+	kunmap_atomic(vaddr_old);
+
+	ret = anon_vma_prepare(vma);
+	if (ret)
+		goto unlock_out;
+
+	lock_page(new_page);
+	ret = __replace_page(vma, old_page, new_page);
+	unlock_page(new_page);
+
+unlock_out:
+	unlock_page(old_page);
+	page_cache_release(new_page);
+
+put_out:
+	put_page(old_page);	/* we did a get_page in the beginning */
+	return ret;
+}
+
+/**
+ * read_opcode - read the opcode at a given virtual address.
+ * @mm: the probed process address space.
+ * @vaddr: the virtual address to read the opcode.
+ * @opcode: location to store the read opcode.
+ *
+ * Called with mm->mmap_sem held (for read and with a reference to
+ * mm.
+ *
+ * For mm @mm, read the opcode at @vaddr and store it in @opcode.
+ * Return 0 (success) or a negative errno.
+ */
+static int read_opcode(struct mm_struct *mm, unsigned long vaddr,
+						uprobe_opcode_t *opcode)
+{
+	struct page *page;
+	void *vaddr_new;
+	int ret;
+
+	ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+	if (ret <= 0)
+		return ret;
+
+	lock_page(page);
+	vaddr_new = kmap_atomic(page);
+	vaddr &= ~PAGE_MASK;
+	memcpy(opcode, vaddr_new + vaddr, uprobe_opcode_sz);
+	kunmap_atomic(vaddr_new);
+	unlock_page(page);
+	put_page(page);		/* we did a get_user_pages in the beginning */
+	return 0;
+}
+
+static int is_bkpt_at_addr(struct mm_struct *mm, unsigned long vaddr)
+{
+	uprobe_opcode_t opcode;
+	int result = read_opcode(mm, vaddr, &opcode);
+
+	if (result)
+		return result;
+
+	if (is_bkpt_insn(&opcode))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * set_bkpt - store breakpoint at a given address.
+ * @mm: the probed process address space.
+ * @uprobe: the probepoint information.
+ * @vaddr: the virtual address to insert the opcode.
+ *
+ * For mm @mm, store the breakpoint instruction at @vaddr.
+ * Return 0 (success) or a negative errno.
+ */
+int __weak set_bkpt(struct mm_struct *mm, struct uprobe *uprobe,
+						unsigned long vaddr)
+{
+	int result = is_bkpt_at_addr(mm, vaddr);
+
+	if (result == 1)
+		return -EEXIST;
+
+	if (result)
+		return result;
+
+	return write_opcode(mm, uprobe, vaddr, UPROBES_BKPT_INSN);
+}
+
+/**
+ * set_orig_insn - Restore the original instruction.
+ * @mm: the probed process address space.
+ * @uprobe: the probepoint information.
+ * @vaddr: the virtual address to insert the opcode.
+ * @verify: if true, verify existance of breakpoint instruction.
+ *
+ * For mm @mm, restore the original opcode (opcode) at @vaddr.
+ * Return 0 (success) or a negative errno.
+ */
+int __weak set_orig_insn(struct mm_struct *mm, struct uprobe *uprobe,
+					unsigned long vaddr, bool verify)
+{
+	if (verify) {
+		int result = is_bkpt_at_addr(mm, vaddr);
+
+		if (!result)
+			return -EINVAL;
+
+		if (result != 1)
+			return result;
+	}
+	return write_opcode(mm, uprobe, vaddr,
+				*(uprobe_opcode_t *)uprobe->insn);
+}
+
+static int match_uprobe(struct uprobe *l, struct uprobe *r)
+{
+	if (l->inode < r->inode)
+		return -1;
+	if (l->inode > r->inode)
+		return 1;
+	else {
+		if (l->offset < r->offset)
+			return -1;
+
+		if (l->offset > r->offset)
+			return 1;
+	}
+
+	return 0;
+}
+
+static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset)
+{
+	struct uprobe u = { .inode = inode, .offset = offset };
+	struct rb_node *n = uprobes_tree.rb_node;
+	struct uprobe *uprobe;
+	int match;
+
+	while (n) {
+		uprobe = rb_entry(n, struct uprobe, rb_node);
+		match = match_uprobe(&u, uprobe);
+		if (!match) {
+			atomic_inc(&uprobe->ref);
+			return uprobe;
+		}
+		if (match < 0)
+			n = n->rb_left;
+		else
+			n = n->rb_right;
+	}
+	return NULL;
+}
+
+/*
+ * Find a uprobe corresponding to a given inode:offset
+ * Acquires uprobes_treelock
+ */
+static struct uprobe *find_uprobe(struct inode *inode, loff_t offset)
+{
+	struct uprobe *uprobe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uprobes_treelock, flags);
+	uprobe = __find_uprobe(inode, offset);
+	spin_unlock_irqrestore(&uprobes_treelock, flags);
+	return uprobe;
+}
+
+static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
+{
+	struct rb_node **p = &uprobes_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct uprobe *u;
+	int match;
+
+	while (*p) {
+		parent = *p;
+		u = rb_entry(parent, struct uprobe, rb_node);
+		match = match_uprobe(uprobe, u);
+		if (!match) {
+			atomic_inc(&u->ref);
+			return u;
+		}
+
+		if (match < 0)
+			p = &parent->rb_left;
+		else
+			p = &parent->rb_right;
+
+	}
+	u = NULL;
+	rb_link_node(&uprobe->rb_node, parent, p);
+	rb_insert_color(&uprobe->rb_node, &uprobes_tree);
+	/* get access + creation ref */
+	atomic_set(&uprobe->ref, 2);
+	return u;
+}
+
+/*
+ * Acquires uprobes_treelock.
+ * Matching uprobe already exists in rbtree;
+ *	increment (access refcount) and return the matching uprobe.
+ *
+ * No matching uprobe; insert the uprobe in rb_tree;
+ *	get a double refcount (access + creation) and return NULL.
+ */
+static struct uprobe *insert_uprobe(struct uprobe *uprobe)
+{
+	unsigned long flags;
+	struct uprobe *u;
+
+	spin_lock_irqsave(&uprobes_treelock, flags);
+	u = __insert_uprobe(uprobe);
+	spin_unlock_irqrestore(&uprobes_treelock, flags);
+
+	/* For now assume that the instruction need not be single-stepped */
+	uprobe->flags |= UPROBES_SKIP_SSTEP;
+	return u;
+}
+
+static void put_uprobe(struct uprobe *uprobe)
+{
+	if (atomic_dec_and_test(&uprobe->ref))
+		kfree(uprobe);
+}
+
+static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
+{
+	struct uprobe *uprobe, *cur_uprobe;
+
+	uprobe = kzalloc(sizeof(struct uprobe), GFP_KERNEL);
+	if (!uprobe)
+		return NULL;
+
+	uprobe->inode = igrab(inode);
+	uprobe->offset = offset;
+	init_rwsem(&uprobe->consumer_rwsem);
+	INIT_LIST_HEAD(&uprobe->pending_list);
+
+	/* add to uprobes_tree, sorted on inode:offset */
+	cur_uprobe = insert_uprobe(uprobe);
+
+	/* a uprobe exists for this inode:offset combination */
+	if (cur_uprobe) {
+		kfree(uprobe);
+		uprobe = cur_uprobe;
+		iput(inode);
+	} else
+		atomic_inc(&uprobe_events);
+	return uprobe;
+}
+
+static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
+{
+	struct uprobe_consumer *consumer;
+
+	if (!(uprobe->flags & UPROBES_RUN_HANDLER))
+		return;
+
+	down_read(&uprobe->consumer_rwsem);
+	consumer = uprobe->consumers;
+	for (consumer = uprobe->consumers; consumer;
+					consumer = consumer->next) {
+		if (!consumer->filter ||
+				consumer->filter(consumer, current))
+			consumer->handler(consumer, regs);
+	}
+	up_read(&uprobe->consumer_rwsem);
+}
+
+/* Returns the previous consumer */
+static struct uprobe_consumer *add_consumer(struct uprobe *uprobe,
+				struct uprobe_consumer *consumer)
+{
+	down_write(&uprobe->consumer_rwsem);
+	consumer->next = uprobe->consumers;
+	uprobe->consumers = consumer;
+	up_write(&uprobe->consumer_rwsem);
+	return consumer->next;
+}
+
+/*
+ * For uprobe @uprobe, delete the consumer @consumer.
+ * Return true if the @consumer is deleted successfully
+ * or return false.
+ */
+static bool del_consumer(struct uprobe *uprobe,
+				struct uprobe_consumer *consumer)
+{
+	struct uprobe_consumer **con;
+	bool ret = false;
+
+	down_write(&uprobe->consumer_rwsem);
+	for (con = &uprobe->consumers; *con; con = &(*con)->next) {
+		if (*con == consumer) {
+			*con = consumer->next;
+			ret = true;
+			break;
+		}
+	}
+	up_write(&uprobe->consumer_rwsem);
+	return ret;
+}
+
+static int __copy_insn(struct address_space *mapping,
+			struct vm_area_struct *vma, char *insn,
+			unsigned long nbytes, unsigned long offset)
+{
+	struct file *filp = vma->vm_file;
+	struct page *page;
+	void *vaddr;
+	unsigned long off1;
+	unsigned long idx;
+
+	if (!filp)
+		return -EINVAL;
+
+	idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT);
+	off1 = offset &= ~PAGE_MASK;
+
+	/*
+	 * Ensure that the page that has the original instruction is
+	 * populated and in page-cache.
+	 */
+	page = read_mapping_page(mapping, idx, filp);
+	if (IS_ERR(page))
+		return PTR_ERR(page);
+
+	vaddr = kmap_atomic(page);
+	memcpy(insn, vaddr + off1, nbytes);
+	kunmap_atomic(vaddr);
+	page_cache_release(page);
+	return 0;
+}
+
+static int copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma,
+					unsigned long addr)
+{
+	struct address_space *mapping;
+	int bytes;
+	unsigned long nbytes;
+
+	addr &= ~PAGE_MASK;
+	nbytes = PAGE_SIZE - addr;
+	mapping = uprobe->inode->i_mapping;
+
+	/* Instruction at end of binary; copy only available bytes */
+	if (uprobe->offset + MAX_UINSN_BYTES > uprobe->inode->i_size)
+		bytes = uprobe->inode->i_size - uprobe->offset;
+	else
+		bytes = MAX_UINSN_BYTES;
+
+	/* Instruction at the page-boundary; copy bytes in second page */
+	if (nbytes < bytes) {
+		if (__copy_insn(mapping, vma, uprobe->insn + nbytes,
+				bytes - nbytes, uprobe->offset + nbytes))
+			return -ENOMEM;
+
+		bytes = nbytes;
+	}
+	return __copy_insn(mapping, vma, uprobe->insn, bytes, uprobe->offset);
+}
+
+/*
+ * How mm_uprobes_count gets updated
+ * mmap_uprobe() increments the count if
+ * 	- it successfully adds a breakpoint.
+ * 	- it not add a breakpoint, but sees that there is a underlying
+ * 	  breakpoint (via a is_bkpt_at_addr()).
+ *
+ * munmap_uprobe() decrements the count if
+ * 	- it sees a underlying breakpoint, (via is_bkpt_at_addr)
+ * 	- Subsequent unregister_uprobe wouldnt find the breakpoint
+ * 	  unless a mmap_uprobe kicks in, since the old vma would be
+ * 	  dropped just after munmap_uprobe.
+ *
+ * register_uprobe increments the count if:
+ * 	- it successfully adds a breakpoint.
+ *
+ * unregister_uprobe decrements the count if:
+ * 	- it sees a underlying breakpoint and removes successfully.
+ * 			(via is_bkpt_at_addr)
+ * 	- Subsequent munmap_uprobe wouldnt find the breakpoint
+ * 	  since there is no underlying breakpoint after the
+ * 	  breakpoint removal.
+ */
+
+static int install_breakpoint(struct mm_struct *mm, struct uprobe *uprobe,
+				struct vm_area_struct *vma, loff_t vaddr)
+{
+	unsigned long addr;
+	int ret;
+
+	/*
+	 * If probe is being deleted, unregister thread could be done with
+	 * the vma-rmap-walk through. Adding a probe now can be fatal since
+	 * nobody will be able to cleanup. Also we could be from fork or
+	 * mremap path, where the probe might have already been inserted.
+	 * Hence behave as if probe already existed.
+	 */
+	if (!uprobe->consumers)
+		return -EEXIST;
+
+	addr = (unsigned long)vaddr;
+	if (!(uprobe->flags & UPROBES_COPY_INSN)) {
+		ret = copy_insn(uprobe, vma, addr);
+		if (ret)
+			return ret;
+
+		if (is_bkpt_insn((uprobe_opcode_t *)uprobe->insn))
+			return -EEXIST;
+
+		ret = analyze_insn(mm, uprobe);
+		if (ret)
+			return ret;
+
+		uprobe->flags |= UPROBES_COPY_INSN;
+	}
+
+	/*
+	 * Ideally, should be updating the probe count after the breakpoint
+	 * has been successfully inserted. However a thread could hit the
+	 * breakpoint we just inserted even before the probe count is
+	 * incremented. If this is the first breakpoint placed, breakpoint
+	 * notifier might ignore uprobes and pass the trap to the thread.
+	 * Hence increment before and decrement on failure.
+	 */
+	atomic_inc(&mm->mm_uprobes_count);
+	ret = set_bkpt(mm, uprobe, addr);
+	if (ret)
+		atomic_dec(&mm->mm_uprobes_count);
+
+	return ret;
+}
+
+static void remove_breakpoint(struct mm_struct *mm, struct uprobe *uprobe,
+							loff_t vaddr)
+{
+	if (!set_orig_insn(mm, uprobe, (unsigned long)vaddr, true))
+		atomic_dec(&mm->mm_uprobes_count);
+}
+
+/*
+ * There could be threads that have hit the breakpoint and are entering the
+ * notifier code and trying to acquire the uprobes_treelock. The thread
+ * calling delete_uprobe() that is removing the uprobe from the rb_tree can
+ * race with these threads and might acquire the uprobes_treelock compared
+ * to some of the breakpoint hit threads. In such a case, the breakpoint hit
+ * threads will not find the uprobe. Hence wait till the current breakpoint
+ * hit threads acquire the uprobes_treelock before the uprobe is removed
+ * from the rbtree.
+ */
+static void delete_uprobe(struct uprobe *uprobe)
+{
+	unsigned long flags;
+
+	synchronize_srcu(&uprobes_srcu);
+	spin_lock_irqsave(&uprobes_treelock, flags);
+	rb_erase(&uprobe->rb_node, &uprobes_tree);
+	spin_unlock_irqrestore(&uprobes_treelock, flags);
+	iput(uprobe->inode);
+	put_uprobe(uprobe);
+	atomic_dec(&uprobe_events);
+}
+
+static struct vma_info *__find_next_vma_info(struct list_head *head,
+			loff_t offset, struct address_space *mapping,
+			struct vma_info *vi, bool is_register)
+{
+	struct prio_tree_iter iter;
+	struct vm_area_struct *vma;
+	struct vma_info *tmpvi;
+	loff_t vaddr;
+	unsigned long pgoff = offset >> PAGE_SHIFT;
+	int existing_vma;
+
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+		if (!valid_vma(vma, is_register))
+			continue;
+
+		existing_vma = 0;
+		vaddr = vma_address(vma, offset);
+		list_for_each_entry(tmpvi, head, probe_list) {
+			if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) {
+				existing_vma = 1;
+				break;
+			}
+		}
+
+		/*
+		 * Another vma needs a probe to be installed. However skip
+		 * installing the probe if the vma is about to be unlinked.
+		 */
+		if (!existing_vma &&
+				atomic_inc_not_zero(&vma->vm_mm->mm_users)) {
+			vi->mm = vma->vm_mm;
+			vi->vaddr = vaddr;
+			list_add(&vi->probe_list, head);
+			return vi;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Iterate in the rmap prio tree  and find a vma where a probe has not
+ * yet been inserted.
+ */
+static struct vma_info *find_next_vma_info(struct list_head *head,
+			loff_t offset, struct address_space *mapping,
+			bool is_register)
+{
+	struct vma_info *vi, *retvi;
+	vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL);
+	if (!vi)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&mapping->i_mmap_mutex);
+	retvi = __find_next_vma_info(head, offset, mapping, vi, is_register);
+	mutex_unlock(&mapping->i_mmap_mutex);
+
+	if (!retvi)
+		kfree(vi);
+	return retvi;
+}
+
+static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
+{
+	struct list_head try_list;
+	struct vm_area_struct *vma;
+	struct address_space *mapping;
+	struct vma_info *vi, *tmpvi;
+	struct mm_struct *mm;
+	loff_t vaddr;
+	int ret = 0;
+
+	mapping = uprobe->inode->i_mapping;
+	INIT_LIST_HEAD(&try_list);
+	while ((vi = find_next_vma_info(&try_list, uprobe->offset,
+					mapping, is_register)) != NULL) {
+		if (IS_ERR(vi)) {
+			ret = PTR_ERR(vi);
+			break;
+		}
+		mm = vi->mm;
+		down_read(&mm->mmap_sem);
+		vma = find_vma(mm, (unsigned long)vi->vaddr);
+		if (!vma || !valid_vma(vma, is_register)) {
+			list_del(&vi->probe_list);
+			kfree(vi);
+			up_read(&mm->mmap_sem);
+			mmput(mm);
+			continue;
+		}
+		vaddr = vma_address(vma, uprobe->offset);
+		if (vma->vm_file->f_mapping->host != uprobe->inode ||
+						vaddr != vi->vaddr) {
+			list_del(&vi->probe_list);
+			kfree(vi);
+			up_read(&mm->mmap_sem);
+			mmput(mm);
+			continue;
+		}
+
+		if (is_register)
+			ret = install_breakpoint(mm, uprobe, vma, vi->vaddr);
+		else
+			remove_breakpoint(mm, uprobe, vi->vaddr);
+
+		up_read(&mm->mmap_sem);
+		mmput(mm);
+		if (is_register) {
+			if (ret && ret == -EEXIST)
+				ret = 0;
+			if (ret)
+				break;
+		}
+	}
+	list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) {
+		list_del(&vi->probe_list);
+		kfree(vi);
+	}
+	return ret;
+}
+
+static int __register_uprobe(struct uprobe *uprobe)
+{
+	return register_for_each_vma(uprobe, true);
+}
+
+static void __unregister_uprobe(struct uprobe *uprobe)
+{
+	if (!register_for_each_vma(uprobe, false))
+		delete_uprobe(uprobe);
+
+	/* TODO : cant unregister? schedule a worker thread */
+}
+
+/*
+ * register_uprobe - register a probe
+ * @inode: the file in which the probe has to be placed.
+ * @offset: offset from the start of the file.
+ * @consumer: information on howto handle the probe..
+ *
+ * Apart from the access refcount, register_uprobe() takes a creation
+ * refcount (thro alloc_uprobe) if and only if this @uprobe is getting
+ * inserted into the rbtree (i.e first consumer for a @inode:@offset
+ * tuple).  Creation refcount stops unregister_uprobe from freeing the
+ * @uprobe even before the register operation is complete. Creation
+ * refcount is released when the last @consumer for the @uprobe
+ * unregisters.
+ *
+ * Return errno if it cannot successully install probes
+ * else return 0 (success)
+ */
+int register_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer)
+{
+	struct uprobe *uprobe;
+	int ret = -EINVAL;
+
+	if (!inode || !consumer || consumer->next)
+		return ret;
+
+	if (offset > i_size_read(inode))
+		return ret;
+
+	ret = 0;
+	mutex_lock(uprobes_hash(inode));
+	uprobe = alloc_uprobe(inode, offset);
+	if (uprobe && !add_consumer(uprobe, consumer)) {
+		ret = __register_uprobe(uprobe);
+		if (ret) {
+			uprobe->consumers = NULL;
+			__unregister_uprobe(uprobe);
+		} else
+			uprobe->flags |= UPROBES_RUN_HANDLER;
+	}
+
+	mutex_unlock(uprobes_hash(inode));
+	put_uprobe(uprobe);
+
+	return ret;
+}
+
+/*
+ * unregister_uprobe - unregister a already registered probe.
+ * @inode: the file in which the probe has to be removed.
+ * @offset: offset from the start of the file.
+ * @consumer: identify which probe if multiple probes are colocated.
+ */
+void unregister_uprobe(struct inode *inode, loff_t offset,
+				struct uprobe_consumer *consumer)
+{
+	struct uprobe *uprobe = NULL;
+
+	if (!inode || !consumer)
+		return;
+
+	uprobe = find_uprobe(inode, offset);
+	if (!uprobe)
+		return;
+
+	mutex_lock(uprobes_hash(inode));
+	if (!del_consumer(uprobe, consumer))
+		goto unreg_out;
+
+	if (!uprobe->consumers) {
+		__unregister_uprobe(uprobe);
+		uprobe->flags &= ~UPROBES_RUN_HANDLER;
+	}
+
+unreg_out:
+	mutex_unlock(uprobes_hash(inode));
+	if (uprobe)
+		put_uprobe(uprobe);
+}
+
+/*
+ * Of all the nodes that correspond to the given inode, return the node
+ * with the least offset.
+ */
+static struct rb_node *find_least_offset_node(struct inode *inode)
+{
+	struct uprobe u = { .inode = inode, .offset = 0};
+	struct rb_node *n = uprobes_tree.rb_node;
+	struct rb_node *close_node = NULL;
+	struct uprobe *uprobe;
+	int match;
+
+	while (n) {
+		uprobe = rb_entry(n, struct uprobe, rb_node);
+		match = match_uprobe(&u, uprobe);
+		if (uprobe->inode == inode)
+			close_node = n;
+
+		if (!match)
+			return close_node;
+
+		if (match < 0)
+			n = n->rb_left;
+		else
+			n = n->rb_right;
+	}
+	return close_node;
+}
+
+/*
+ * For a given inode, build a list of probes that need to be inserted.
+ */
+static void build_probe_list(struct inode *inode, struct list_head *head)
+{
+	struct uprobe *uprobe;
+	struct rb_node *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uprobes_treelock, flags);
+	n = find_least_offset_node(inode);
+	for (; n; n = rb_next(n)) {
+		uprobe = rb_entry(n, struct uprobe, rb_node);
+		if (uprobe->inode != inode)
+			break;
+
+		list_add(&uprobe->pending_list, head);
+		atomic_inc(&uprobe->ref);
+	}
+	spin_unlock_irqrestore(&uprobes_treelock, flags);
+}
+
+/*
+ * Called from mmap_region.
+ * called with mm->mmap_sem acquired.
+ *
+ * Return -ve no if we fail to insert probes and we cannot
+ * bail-out.
+ * Return 0 otherwise. i.e :
+ *	- successful insertion of probes
+ *	- (or) no possible probes to be inserted.
+ *	- (or) insertion of probes failed but we can bail-out.
+ */
+int mmap_uprobe(struct vm_area_struct *vma)
+{
+	struct list_head tmp_list;
+	struct uprobe *uprobe, *u;
+	struct inode *inode;
+	int ret = 0, count = 0;
+
+	if (!atomic_read(&uprobe_events) || !valid_vma(vma, true))
+		return ret;	/* Bail-out */
+
+	inode = vma->vm_file->f_mapping->host;
+	if (!inode)
+		return ret;
+
+	INIT_LIST_HEAD(&tmp_list);
+	mutex_lock(uprobes_mmap_hash(inode));
+	build_probe_list(inode, &tmp_list);
+	list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
+		loff_t vaddr;
+
+		list_del(&uprobe->pending_list);
+		if (!ret) {
+			vaddr = vma_address(vma, uprobe->offset);
+			if (vaddr < vma->vm_start || vaddr >= vma->vm_end) {
+				put_uprobe(uprobe);
+				continue;
+			}
+			ret = install_breakpoint(vma->vm_mm, uprobe, vma,
+								vaddr);
+			if (ret == -EEXIST) {
+				ret = 0;
+				if (!is_bkpt_at_addr(vma->vm_mm, vaddr))
+					continue;
+
+				/*
+				 * Unable to insert a breakpoint, but
+				 * breakpoint lies underneath. Increment the
+				 * probe count.
+				 */
+				atomic_inc(&vma->vm_mm->mm_uprobes_count);
+			}
+			if (!ret)
+				count++;
+
+		}
+		put_uprobe(uprobe);
+	}
+
+	mutex_unlock(uprobes_mmap_hash(inode));
+	if (ret)
+		atomic_sub(count, &vma->vm_mm->mm_uprobes_count);
+
+	return ret;
+}
+
+/*
+ * Called in context of a munmap of a vma.
+ */
+void munmap_uprobe(struct vm_area_struct *vma)
+{
+	struct list_head tmp_list;
+	struct uprobe *uprobe, *u;
+	struct inode *inode;
+
+	if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
+		return;		/* Bail-out */
+
+	if (!atomic_read(&vma->vm_mm->mm_uprobes_count))
+		return;
+
+	inode = vma->vm_file->f_mapping->host;
+	if (!inode)
+		return;
+
+	INIT_LIST_HEAD(&tmp_list);
+	mutex_lock(uprobes_mmap_hash(inode));
+	build_probe_list(inode, &tmp_list);
+	list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
+		loff_t vaddr;
+
+		list_del(&uprobe->pending_list);
+		vaddr = vma_address(vma, uprobe->offset);
+		if (vaddr >= vma->vm_start && vaddr < vma->vm_end) {
+
+			/*
+			 * An unregister could have removed the probe before
+			 * unmap. So check before we decrement the count.
+			 */
+			if (is_bkpt_at_addr(vma->vm_mm, vaddr) == 1)
+				atomic_dec(&vma->vm_mm->mm_uprobes_count);
+		}
+		put_uprobe(uprobe);
+	}
+	mutex_unlock(uprobes_mmap_hash(inode));
+	return;
+}
+
+/* Slot allocation for XOL */
+static int xol_add_vma(struct uprobes_xol_area *area)
+{
+	struct mm_struct *mm;
+	int ret;
+
+	area->page = alloc_page(GFP_HIGHUSER);
+	if (!area->page)
+		return -ENOMEM;
+
+	mm = current->mm;
+	down_write(&mm->mmap_sem);
+	ret = -EALREADY;
+	if (mm->uprobes_xol_area)
+		goto fail;
+
+	ret = -ENOMEM;
+
+	/* Try to map as high as possible, this is only a hint. */
+	area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE,
+							PAGE_SIZE, 0, 0);
+	if (area->vaddr & ~PAGE_MASK) {
+		ret = area->vaddr;
+		goto fail;
+	}
+
+	ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
+				VM_EXEC|VM_MAYEXEC|VM_DONTCOPY|VM_IO,
+				&area->page);
+	if (ret)
+		goto fail;
+
+	smp_wmb();	/* pairs with get_uprobes_xol_area() */
+	mm->uprobes_xol_area = area;
+	ret = 0;
+
+fail:
+	up_write(&mm->mmap_sem);
+	if (ret)
+		__free_page(area->page);
+
+	return ret;
+}
+
+static struct uprobes_xol_area *get_uprobes_xol_area(struct mm_struct *mm)
+{
+	struct uprobes_xol_area *area = mm->uprobes_xol_area;
+	smp_read_barrier_depends();/* pairs with wmb in xol_add_vma() */
+	return area;
+}
+
+/*
+ * xol_alloc_area - Allocate process's uprobes_xol_area.
+ * This area will be used for storing instructions for execution out of
+ * line.
+ *
+ * Returns the allocated area or NULL.
+ */
+static struct uprobes_xol_area *xol_alloc_area(void)
+{
+	struct uprobes_xol_area *area;
+
+	area = kzalloc(sizeof(*area), GFP_KERNEL);
+	if (unlikely(!area))
+		return NULL;
+
+	area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long),
+								GFP_KERNEL);
+
+	if (!area->bitmap)
+		goto fail;
+
+	init_waitqueue_head(&area->wq);
+	if (!xol_add_vma(area))
+		return area;
+
+fail:
+	kfree(area->bitmap);
+	kfree(area);
+	return get_uprobes_xol_area(current->mm);
+}
+
+/*
+ * free_uprobes_xol_area - Free the area allocated for slots.
+ */
+void free_uprobes_xol_area(struct mm_struct *mm)
+{
+	struct uprobes_xol_area *area = mm->uprobes_xol_area;
+
+	if (!area)
+		return;
+
+	put_page(area->page);
+	kfree(area->bitmap);
+	kfree(area);
+}
+
+/*
+ *  - search for a free slot.
+ */
+static unsigned long xol_take_insn_slot(struct uprobes_xol_area *area)
+{
+	unsigned long slot_addr;
+	int slot_nr;
+
+	do {
+		slot_nr = find_first_zero_bit(area->bitmap, UINSNS_PER_PAGE);
+		if (slot_nr < UINSNS_PER_PAGE) {
+			if (!test_and_set_bit(slot_nr, area->bitmap))
+				break;
+
+			slot_nr = UINSNS_PER_PAGE;
+			continue;
+		}
+		wait_event(area->wq,
+			(atomic_read(&area->slot_count) < UINSNS_PER_PAGE));
+	} while (slot_nr >= UINSNS_PER_PAGE);
+
+	slot_addr = area->vaddr + (slot_nr * UPROBES_XOL_SLOT_BYTES);
+	atomic_inc(&area->slot_count);
+	return slot_addr;
+}
+
+/*
+ * xol_get_insn_slot - If was not allocated a slot, then
+ * allocate a slot.
+ * Returns the allocated slot address or 0.
+ */
+static unsigned long xol_get_insn_slot(struct uprobe *uprobe,
+					unsigned long slot_addr)
+{
+	struct uprobes_xol_area *area;
+	unsigned long offset;
+	void *vaddr;
+
+	area = get_uprobes_xol_area(current->mm);
+	if (!area) {
+		area = xol_alloc_area();
+		if (!area)
+			return 0;
+	}
+	current->utask->xol_vaddr = xol_take_insn_slot(area);
+
+	/*
+	 * Initialize the slot if xol_vaddr points to valid
+	 * instruction slot.
+	 */
+	if (unlikely(!current->utask->xol_vaddr))
+		return 0;
+
+	current->utask->vaddr = slot_addr;
+	offset = current->utask->xol_vaddr & ~PAGE_MASK;
+	vaddr = kmap_atomic(area->page);
+	memcpy(vaddr + offset, uprobe->insn, MAX_UINSN_BYTES);
+	kunmap_atomic(vaddr);
+	return current->utask->xol_vaddr;
+}
+
+/*
+ * xol_free_insn_slot - If slot was earlier allocated by
+ * @xol_get_insn_slot(), make the slot available for
+ * subsequent requests.
+ */
+static void xol_free_insn_slot(struct task_struct *tsk)
+{
+	struct uprobes_xol_area *area;
+	unsigned long vma_end;
+	unsigned long slot_addr;
+
+	if (!tsk->mm || !tsk->mm->uprobes_xol_area || !tsk->utask)
+		return;
+
+	slot_addr = tsk->utask->xol_vaddr;
+
+	if (unlikely(!slot_addr || IS_ERR_VALUE(slot_addr)))
+		return;
+
+	area = tsk->mm->uprobes_xol_area;
+	vma_end = area->vaddr + PAGE_SIZE;
+	if (area->vaddr <= slot_addr && slot_addr < vma_end) {
+		int slot_nr;
+		unsigned long offset = slot_addr - area->vaddr;
+
+		slot_nr = offset / UPROBES_XOL_SLOT_BYTES;
+		if (slot_nr >= UINSNS_PER_PAGE)
+			return;
+
+		clear_bit(slot_nr, area->bitmap);
+		atomic_dec(&area->slot_count);
+		if (waitqueue_active(&area->wq))
+			wake_up(&area->wq);
+		tsk->utask->xol_vaddr = 0;
+	}
+}
+
+/**
+ * get_uprobe_bkpt_addr - compute address of bkpt given post-bkpt regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ */
+unsigned long __weak get_uprobe_bkpt_addr(struct pt_regs *regs)
+{
+	return instruction_pointer(regs) - UPROBES_BKPT_INSN_SIZE;
+}
+
+/*
+ * Called with no locks held.
+ * Called in context of a exiting or a exec-ing thread.
+ */
+void free_uprobe_utask(struct task_struct *tsk)
+{
+	struct uprobe_task *utask = tsk->utask;
+
+	if (tsk->uprobes_srcu_id != -1)
+		srcu_read_unlock_raw(&uprobes_srcu, tsk->uprobes_srcu_id);
+
+	if (!utask)
+		return;
+
+	if (utask->active_uprobe)
+		put_uprobe(utask->active_uprobe);
+
+	xol_free_insn_slot(tsk);
+	kfree(utask);
+	tsk->utask = NULL;
+}
+
+/*
+ * Allocate a uprobe_task object for the task.
+ * Called when the thread hits a breakpoint for the first time.
+ *
+ * Returns:
+ * - pointer to new uprobe_task on success
+ * - NULL otherwise
+ */
+static struct uprobe_task *add_utask(void)
+{
+	struct uprobe_task *utask;
+
+	utask = kzalloc(sizeof *utask, GFP_KERNEL);
+	if (unlikely(utask == NULL))
+		return NULL;
+
+	utask->active_uprobe = NULL;
+	current->utask = utask;
+	return utask;
+}
+
+/* Prepare to single-step probed instruction out of line. */
+static int pre_ssout(struct uprobe *uprobe, struct pt_regs *regs,
+				unsigned long vaddr)
+{
+	if (xol_get_insn_slot(uprobe, vaddr) && !pre_xol(uprobe, regs))
+		return 0;
+	return -EFAULT;
+}
+
+/*
+ * If we are singlestepping, then ensure this thread is not connected to
+ * non-fatal signals until completion of singlestep.  When xol insn itself
+ * triggers the signal,  restart the original insn even if the task is
+ * already SIGKILL'ed (since coredump should report the correct ip).  This
+ * is even more important if the task has a handler for SIGSEGV/etc, The
+ * _same_ instruction should be repeated again after return from the signal
+ * handler, and SSTEP can never finish in this case.
+ */
+bool uprobe_deny_signal(void)
+{
+	struct task_struct *tsk = current;
+	struct uprobe_task *utask = tsk->utask;
+
+	if (likely(!utask || !utask->active_uprobe))
+		return false;
+
+	WARN_ON_ONCE(utask->state != UTASK_SSTEP);
+
+	if (signal_pending(tsk)) {
+		spin_lock_irq(&tsk->sighand->siglock);
+		clear_tsk_thread_flag(tsk, TIF_SIGPENDING);
+		spin_unlock_irq(&tsk->sighand->siglock);
+
+		if (__fatal_signal_pending(tsk) || xol_was_trapped(tsk)) {
+			utask->state = UTASK_SSTEP_TRAPPED;
+			set_tsk_thread_flag(tsk, TIF_UPROBE);
+			set_tsk_thread_flag(tsk, TIF_NOTIFY_RESUME);
+		}
+	}
+
+	return true;
+}
+
+bool __weak can_skip_xol(struct pt_regs *regs, struct uprobe *u)
+{
+	u->flags &= ~UPROBES_SKIP_SSTEP;
+	return false;
+}
+
+/*
+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag.  (and on
+ * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and
+ * allows the thread to return from interrupt.  While returning to
+ * userspace, thread noticies the TIF_UPROBE flag and calls
+ * uprobe_notify_resume(). uprobe_notify_resume will run the handler and ask
+ * the thread to singlestep.
+ *
+ * On subsequent singlestep exception, singlestep notifier sets the
+ * TIF_UPROBE flag and also sets the state to UTASK_SSTEP_ACK and allows the
+ * thread to return from interrupt. While returning to userspace, thread
+ * notices the TIF_UPROBE and calls uprobe_notify_resume().
+ * uprobe_notify_resume disables singlestep and performs the required
+ * fix-ups.
+ *
+ * All non-fatal signals cannot interrupt thread while the thread singlesteps.
+ */
+void uprobe_notify_resume(struct pt_regs *regs)
+{
+	struct vm_area_struct *vma;
+	struct uprobe_task *utask;
+	struct mm_struct *mm;
+	struct uprobe *u = NULL;
+	unsigned long probept;
+
+	utask = current->utask;
+	mm = current->mm;
+	if (!utask || utask->state == UTASK_BP_HIT) {
+		probept = get_uprobe_bkpt_addr(regs);
+		down_read(&mm->mmap_sem);
+		vma = find_vma(mm, probept);
+		if (vma && vma->vm_start <= probept && valid_vma(vma, false))
+			u = find_uprobe(vma->vm_file->f_mapping->host,
+					probept - vma->vm_start +
+					(vma->vm_pgoff << PAGE_SHIFT));
+
+		srcu_read_unlock_raw(&uprobes_srcu,
+					current->uprobes_srcu_id);
+		current->uprobes_srcu_id = -1;
+		up_read(&mm->mmap_sem);
+		if (!u)
+			/* No matching uprobe; signal SIGTRAP. */
+			goto cleanup_ret;
+		if (!utask) {
+			utask = add_utask();
+			/* Cannot Allocate; re-execute the instruction. */
+			if (!utask)
+				goto cleanup_ret;
+		}
+		utask->active_uprobe = u;
+		handler_chain(u, regs);
+
+		if (u->flags & UPROBES_SKIP_SSTEP && can_skip_xol(regs, u))
+			goto cleanup_ret;
+
+		utask->state = UTASK_SSTEP;
+		if (!pre_ssout(u, regs, probept))
+			user_enable_single_step(current);
+		else
+			/* Cannot Singlestep; re-execute the instruction. */
+			goto cleanup_ret;
+	} else {
+		u = utask->active_uprobe;
+		if (utask->state == UTASK_SSTEP_ACK)
+			post_xol(u, regs);
+		else if (utask->state == UTASK_SSTEP_TRAPPED)
+			abort_xol(regs, u);
+		else
+			WARN_ON_ONCE(1);
+
+		put_uprobe(u);
+		utask->active_uprobe = NULL;
+		utask->state = UTASK_RUNNING;
+		user_disable_single_step(current);
+		xol_free_insn_slot(current);
+
+		spin_lock_irq(&current->sighand->siglock);
+		recalc_sigpending(); /* see uprobe_deny_signal() */
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+	return;
+
+cleanup_ret:
+	if (utask) {
+		utask->active_uprobe = NULL;
+		utask->state = UTASK_RUNNING;
+	}
+	if (u) {
+		if (!(u->flags & UPROBES_SKIP_SSTEP))
+			set_instruction_pointer(regs, probept);
+
+		put_uprobe(u);
+	} else
+		send_sig(SIGTRAP, current, 0);
+}
+
+/*
+ * uprobe_bkpt_notifier gets called from interrupt context as part of
+ * notifier mechanism. Set TIF_UPROBE flag and indicate breakpoint hit.
+ */
+int uprobe_bkpt_notifier(struct pt_regs *regs)
+{
+	struct uprobe_task *utask;
+
+	if (!current->mm || !atomic_read(&current->mm->mm_uprobes_count))
+		/* task is currently not uprobed */
+		return 0;
+
+	utask = current->utask;
+	if (utask)
+		utask->state = UTASK_BP_HIT;
+
+	set_thread_flag(TIF_UPROBE);
+	current->uprobes_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
+	return 1;
+}
+
+/*
+ * uprobe_post_notifier gets called in interrupt context as part of notifier
+ * mechanism. Set TIF_UPROBE flag and indicate completion of singlestep.
+ */
+int uprobe_post_notifier(struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	if (!current->mm || !utask || !utask->active_uprobe)
+		/* task is currently not uprobed */
+		return 0;
+
+	utask->state = UTASK_SSTEP_ACK;
+	set_thread_flag(TIF_UPROBE);
+	return 1;
+}
+
+struct notifier_block uprobe_exception_nb = {
+	.notifier_call = uprobe_exception_notify,
+	.priority = INT_MAX - 1,	/* notified after kprobes, kgdb */
+};
+
+static int __init init_uprobes(void)
+{
+	int i;
+
+	for (i = 0; i < UPROBES_HASH_SZ; i++) {
+		mutex_init(&uprobes_mutex[i]);
+		mutex_init(&uprobes_mmap_mutex[i]);
+	}
+	init_srcu_struct(&uprobes_srcu);
+	return register_die_notifier(&uprobe_exception_nb);
+}
+
+static void __exit exit_uprobes(void)
+{
+}
+
+module_init(init_uprobes);
+module_exit(exit_uprobes);
diff --git a/lib/Kconfig b/lib/Kconfig
index 169eb7c..203efe1 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -58,14 +58,67 @@ config CRC_ITU_T
 	  functions require M here.
 
 config CRC32
-	tristate "CRC32 functions"
+	tristate "CRC32/CRC32c functions"
 	default y
 	select BITREVERSE
 	help
 	  This option is provided for the case where no in-kernel-tree
-	  modules require CRC32 functions, but a module built outside the
-	  kernel tree does. Such modules that use library CRC32 functions
-	  require M here.
+	  modules require CRC32/CRC32c functions, but a module built outside
+	  the kernel tree does. Such modules that use library CRC32/CRC32c
+	  functions require M here.
+
+config CRC32_SELFTEST
+	bool "CRC32 perform self test on init"
+	default n
+	depends on CRC32
+	help
+	  This option enables the CRC32 library functions to perform a
+	  self test on initialization. The self test computes crc32_le
+	  and crc32_be over byte strings with random alignment and length
+	  and computes the total elapsed time and number of bytes processed.
+
+choice
+	prompt "CRC32 implementation"
+	depends on CRC32
+	default CRC32_SLICEBY8
+
+config CRC32_SLICEBY8
+	bool "Slice by 8 bytes"
+	help
+	  Calculate checksum 8 bytes at a time with a clever slicing algorithm.
+	  This is the fastest algorithm, but comes with a 8KiB lookup table.
+	  Most modern processors have enough cache to hold this table without
+	  thrashing the cache.
+
+	  This is the default implementation choice.  Choose this one unless
+	  you have a good reason not to.
+
+config CRC32_SLICEBY4
+	bool "Slice by 4 bytes"
+	help
+	  Calculate checksum 4 bytes at a time with a clever slicing algorithm.
+	  This is a bit slower than slice by 8, but has a smaller 4KiB lookup
+	  table.
+
+	  Only choose this option if you know what you are doing.
+
+config CRC32_SARWATE
+	bool "Sarwate's Algorithm (one byte at a time)"
+	help
+	  Calculate checksum a byte at a time using Sarwate's algorithm.  This
+	  is not particularly fast, but has a small 256 byte lookup table.
+
+	  Only choose this option if you know what you are doing.
+
+config CRC32_BIT
+	bool "Classic Algorithm (one bit at a time)"
+	help
+	  Calculate checksum one bit at a time.  This is VERY slow, but has
+	  no lookup table.  This is provided as a debugging option.
+
+	  Only choose this option if you are debugging crc32.
+
+endchoice
 
 config CRC7
 	tristate "CRC7 functions"
diff --git a/lib/crc32.c b/lib/crc32.c
index 4b35d2b..ebc5911 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -1,4 +1,8 @@
 /*
+ * Aug 8, 2011 Bob Pearson with help from Joakim Tjernlund and George Spelvin
+ * cleaned up code to current version of sparse and added the slicing-by-8
+ * algorithm to the closely similar existing slicing-by-4 algorithm.
+ *
  * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com>
  * Nicer crc32 functions/docs submitted by linux@horizon.com.  Thanks!
  * Code was from the public domain, copyright abandoned.  Code was
@@ -20,52 +24,58 @@
  * Version 2.  See the file COPYING for more details.
  */
 
+/* see: Documentation/crc32.txt for a description of algorithms */
+
 #include <linux/crc32.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/compiler.h>
 #include <linux/types.h>
-#include <linux/init.h>
-#include <linux/atomic.h>
 #include "crc32defs.h"
-#if CRC_LE_BITS == 8
-# define tole(x) __constant_cpu_to_le32(x)
+
+#if CRC_LE_BITS > 8
+# define tole(x) ((__force u32) __constant_cpu_to_le32(x))
 #else
 # define tole(x) (x)
 #endif
 
-#if CRC_BE_BITS == 8
-# define tobe(x) __constant_cpu_to_be32(x)
+#if CRC_BE_BITS > 8
+# define tobe(x) ((__force u32) __constant_cpu_to_be32(x))
 #else
 # define tobe(x) (x)
 #endif
+
 #include "crc32table.h"
 
 MODULE_AUTHOR("Matt Domsch <Matt_Domsch@dell.com>");
-MODULE_DESCRIPTION("Ethernet CRC32 calculations");
+MODULE_DESCRIPTION("Various CRC32 calculations");
 MODULE_LICENSE("GPL");
 
-#if CRC_LE_BITS == 8 || CRC_BE_BITS == 8
+#if CRC_LE_BITS > 8 || CRC_BE_BITS > 8
 
+/* implements slicing-by-4 or slicing-by-8 algorithm */
 static inline u32
 crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
 {
 # ifdef __LITTLE_ENDIAN
 #  define DO_CRC(x) crc = t0[(crc ^ (x)) & 255] ^ (crc >> 8)
-#  define DO_CRC4 crc = t3[(crc) & 255] ^ \
-		t2[(crc >> 8) & 255] ^ \
-		t1[(crc >> 16) & 255] ^ \
-		t0[(crc >> 24) & 255]
+#  define DO_CRC4 (t3[(q) & 255] ^ t2[(q >> 8) & 255] ^ \
+		   t1[(q >> 16) & 255] ^ t0[(q >> 24) & 255])
+#  define DO_CRC8 (t7[(q) & 255] ^ t6[(q >> 8) & 255] ^ \
+		   t5[(q >> 16) & 255] ^ t4[(q >> 24) & 255])
 # else
 #  define DO_CRC(x) crc = t0[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
-#  define DO_CRC4 crc = t0[(crc) & 255] ^ \
-		t1[(crc >> 8) & 255] ^  \
-		t2[(crc >> 16) & 255] ^	\
-		t3[(crc >> 24) & 255]
+#  define DO_CRC4 (t0[(q) & 255] ^ t1[(q >> 8) & 255] ^ \
+		   t2[(q >> 16) & 255] ^ t3[(q >> 24) & 255])
+#  define DO_CRC8 (t4[(q) & 255] ^ t5[(q >> 8) & 255] ^ \
+		   t6[(q >> 16) & 255] ^ t7[(q >> 24) & 255])
 # endif
 	const u32 *b;
 	size_t    rem_len;
+# ifdef CONFIG_X86
+	size_t i;
+# endif
 	const u32 *t0=tab[0], *t1=tab[1], *t2=tab[2], *t3=tab[3];
+	const u32 *t4 = tab[4], *t5 = tab[5], *t6 = tab[6], *t7 = tab[7];
+	u32 q;
 
 	/* Align it */
 	if (unlikely((long)buf & 3 && len)) {
@@ -73,27 +83,51 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
 			DO_CRC(*buf++);
 		} while ((--len) && ((long)buf)&3);
 	}
+
+# if CRC_LE_BITS == 32
 	rem_len = len & 3;
-	/* load data 32 bits wide, xor data 32 bits wide. */
 	len = len >> 2;
+# else
+	rem_len = len & 7;
+	len = len >> 3;
+# endif
+
 	b = (const u32 *)buf;
+# ifdef CONFIG_X86
+	--b;
+	for (i = 0; i < len; i++) {
+# else
 	for (--b; len; --len) {
-		crc ^= *++b; /* use pre increment for speed */
-		DO_CRC4;
+# endif
+		q = crc ^ *++b; /* use pre increment for speed */
+# if CRC_LE_BITS == 32
+		crc = DO_CRC4;
+# else
+		crc = DO_CRC8;
+		q = *++b;
+		crc ^= DO_CRC4;
+# endif
 	}
 	len = rem_len;
 	/* And the last few bytes */
 	if (len) {
 		u8 *p = (u8 *)(b + 1) - 1;
+# ifdef CONFIG_X86
+		for (i = 0; i < len; i++)
+			DO_CRC(*++p); /* use pre increment for speed */
+# else
 		do {
 			DO_CRC(*++p); /* use pre increment for speed */
 		} while (--len);
+# endif
 	}
 	return crc;
 #undef DO_CRC
 #undef DO_CRC4
+#undef DO_CRC8
 }
 #endif
+
 /**
  * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
  * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
@@ -101,53 +135,56 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 (*tab)[256])
  * @p: pointer to buffer over which CRC is run
  * @len: length of buffer @p
  */
-u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len);
-
-#if CRC_LE_BITS == 1
-/*
- * In fact, the table-based code will work in this case, but it can be
- * simplified by inlining the table in ?: form.
- */
-
-u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
+static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
+					  size_t len, const u32 (*tab)[256],
+					  u32 polynomial)
 {
+#if CRC_LE_BITS == 1
 	int i;
 	while (len--) {
 		crc ^= *p++;
 		for (i = 0; i < 8; i++)
-			crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+			crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
+	}
+# elif CRC_LE_BITS == 2
+	while (len--) {
+		crc ^= *p++;
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
+		crc = (crc >> 2) ^ tab[0][crc & 3];
 	}
-	return crc;
-}
-#else				/* Table-based approach */
-
-u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
-{
-# if CRC_LE_BITS == 8
-	const u32      (*tab)[] = crc32table_le;
-
-	crc = __cpu_to_le32(crc);
-	crc = crc32_body(crc, p, len, tab);
-	return __le32_to_cpu(crc);
 # elif CRC_LE_BITS == 4
 	while (len--) {
 		crc ^= *p++;
-		crc = (crc >> 4) ^ crc32table_le[crc & 15];
-		crc = (crc >> 4) ^ crc32table_le[crc & 15];
+		crc = (crc >> 4) ^ tab[0][crc & 15];
+		crc = (crc >> 4) ^ tab[0][crc & 15];
 	}
-	return crc;
-# elif CRC_LE_BITS == 2
+# elif CRC_LE_BITS == 8
+	/* aka Sarwate algorithm */
 	while (len--) {
 		crc ^= *p++;
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
-		crc = (crc >> 2) ^ crc32table_le[crc & 3];
+		crc = (crc >> 8) ^ tab[0][crc & 255];
 	}
+# else
+	crc = (__force u32) __cpu_to_le32(crc);
+	crc = crc32_body(crc, p, len, tab);
+	crc = __le32_to_cpu((__force __le32)crc);
+#endif
 	return crc;
-# endif
 }
-#endif
+
+u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
+{
+	return crc32_le_generic(crc, p, len, crc32table_le, CRCPOLY_LE);
+}
+EXPORT_SYMBOL(crc32_le);
+
+u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len)
+{
+	return crc32_le_generic(crc, p, len, crc32ctable_le, CRC32C_POLY_LE);
+}
+EXPORT_SYMBOL(__crc32c_le);
 
 /**
  * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
@@ -156,317 +193,906 @@ u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
  * @p: pointer to buffer over which CRC is run
  * @len: length of buffer @p
  */
-u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len);
-
-#if CRC_BE_BITS == 1
-/*
- * In fact, the table-based code will work in this case, but it can be
- * simplified by inlining the table in ?: form.
- */
-
-u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
+static inline u32 __pure crc32_be_generic(u32 crc, unsigned char const *p,
+					  size_t len, const u32 (*tab)[256],
+					  u32 polynomial)
 {
+#if CRC_BE_BITS == 1
 	int i;
 	while (len--) {
 		crc ^= *p++ << 24;
 		for (i = 0; i < 8; i++)
 			crc =
-			    (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE :
+			    (crc << 1) ^ ((crc & 0x80000000) ? polynomial :
 					  0);
 	}
-	return crc;
-}
-
-#else				/* Table-based approach */
-u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
-{
-# if CRC_BE_BITS == 8
-	const u32      (*tab)[] = crc32table_be;
-
-	crc = __cpu_to_be32(crc);
-	crc = crc32_body(crc, p, len, tab);
-	return __be32_to_cpu(crc);
+# elif CRC_BE_BITS == 2
+	while (len--) {
+		crc ^= *p++ << 24;
+		crc = (crc << 2) ^ tab[0][crc >> 30];
+		crc = (crc << 2) ^ tab[0][crc >> 30];
+		crc = (crc << 2) ^ tab[0][crc >> 30];
+		crc = (crc << 2) ^ tab[0][crc >> 30];
+	}
 # elif CRC_BE_BITS == 4
 	while (len--) {
 		crc ^= *p++ << 24;
-		crc = (crc << 4) ^ crc32table_be[crc >> 28];
-		crc = (crc << 4) ^ crc32table_be[crc >> 28];
+		crc = (crc << 4) ^ tab[0][crc >> 28];
+		crc = (crc << 4) ^ tab[0][crc >> 28];
 	}
-	return crc;
-# elif CRC_BE_BITS == 2
+# elif CRC_BE_BITS == 8
 	while (len--) {
 		crc ^= *p++ << 24;
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
-		crc = (crc << 2) ^ crc32table_be[crc >> 30];
+		crc = (crc << 8) ^ tab[0][crc >> 24];
 	}
-	return crc;
+# else
+	crc = (__force u32) __cpu_to_be32(crc);
+	crc = crc32_body(crc, p, len, tab);
+	crc = __be32_to_cpu((__force __be32)crc);
 # endif
+	return crc;
 }
-#endif
 
-EXPORT_SYMBOL(crc32_le);
+u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
+{
+	return crc32_be_generic(crc, p, len, crc32table_be, CRCPOLY_BE);
+}
 EXPORT_SYMBOL(crc32_be);
 
-/*
- * A brief CRC tutorial.
- *
- * A CRC is a long-division remainder.  You add the CRC to the message,
- * and the whole thing (message+CRC) is a multiple of the given
- * CRC polynomial.  To check the CRC, you can either check that the
- * CRC matches the recomputed value, *or* you can check that the
- * remainder computed on the message+CRC is 0.  This latter approach
- * is used by a lot of hardware implementations, and is why so many
- * protocols put the end-of-frame flag after the CRC.
- *
- * It's actually the same long division you learned in school, except that
- * - We're working in binary, so the digits are only 0 and 1, and
- * - When dividing polynomials, there are no carries.  Rather than add and
- *   subtract, we just xor.  Thus, we tend to get a bit sloppy about
- *   the difference between adding and subtracting.
- *
- * A 32-bit CRC polynomial is actually 33 bits long.  But since it's
- * 33 bits long, bit 32 is always going to be set, so usually the CRC
- * is written in hex with the most significant bit omitted.  (If you're
- * familiar with the IEEE 754 floating-point format, it's the same idea.)
- *
- * Note that a CRC is computed over a string of *bits*, so you have
- * to decide on the endianness of the bits within each byte.  To get
- * the best error-detecting properties, this should correspond to the
- * order they're actually sent.  For example, standard RS-232 serial is
- * little-endian; the most significant bit (sometimes used for parity)
- * is sent last.  And when appending a CRC word to a message, you should
- * do it in the right order, matching the endianness.
- *
- * Just like with ordinary division, the remainder is always smaller than
- * the divisor (the CRC polynomial) you're dividing by.  Each step of the
- * division, you take one more digit (bit) of the dividend and append it
- * to the current remainder.  Then you figure out the appropriate multiple
- * of the divisor to subtract to being the remainder back into range.
- * In binary, it's easy - it has to be either 0 or 1, and to make the
- * XOR cancel, it's just a copy of bit 32 of the remainder.
- *
- * When computing a CRC, we don't care about the quotient, so we can
- * throw the quotient bit away, but subtract the appropriate multiple of
- * the polynomial from the remainder and we're back to where we started,
- * ready to process the next bit.
- *
- * A big-endian CRC written this way would be coded like:
- * for (i = 0; i < input_bits; i++) {
- * 	multiple = remainder & 0x80000000 ? CRCPOLY : 0;
- * 	remainder = (remainder << 1 | next_input_bit()) ^ multiple;
- * }
- * Notice how, to get at bit 32 of the shifted remainder, we look
- * at bit 31 of the remainder *before* shifting it.
- *
- * But also notice how the next_input_bit() bits we're shifting into
- * the remainder don't actually affect any decision-making until
- * 32 bits later.  Thus, the first 32 cycles of this are pretty boring.
- * Also, to add the CRC to a message, we need a 32-bit-long hole for it at
- * the end, so we have to add 32 extra cycles shifting in zeros at the
- * end of every message,
- *
- * So the standard trick is to rearrage merging in the next_input_bit()
- * until the moment it's needed.  Then the first 32 cycles can be precomputed,
- * and merging in the final 32 zero bits to make room for the CRC can be
- * skipped entirely.
- * This changes the code to:
- * for (i = 0; i < input_bits; i++) {
- *      remainder ^= next_input_bit() << 31;
- * 	multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * 	remainder = (remainder << 1) ^ multiple;
- * }
- * With this optimization, the little-endian code is simpler:
- * for (i = 0; i < input_bits; i++) {
- *      remainder ^= next_input_bit();
- * 	multiple = (remainder & 1) ? CRCPOLY : 0;
- * 	remainder = (remainder >> 1) ^ multiple;
- * }
- *
- * Note that the other details of endianness have been hidden in CRCPOLY
- * (which must be bit-reversed) and next_input_bit().
- *
- * However, as long as next_input_bit is returning the bits in a sensible
- * order, we can actually do the merging 8 or more bits at a time rather
- * than one bit at a time:
- * for (i = 0; i < input_bytes; i++) {
- * 	remainder ^= next_input_byte() << 24;
- * 	for (j = 0; j < 8; j++) {
- * 		multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * 		remainder = (remainder << 1) ^ multiple;
- * 	}
- * }
- * Or in little-endian:
- * for (i = 0; i < input_bytes; i++) {
- * 	remainder ^= next_input_byte();
- * 	for (j = 0; j < 8; j++) {
- * 		multiple = (remainder & 1) ? CRCPOLY : 0;
- * 		remainder = (remainder << 1) ^ multiple;
- * 	}
- * }
- * If the input is a multiple of 32 bits, you can even XOR in a 32-bit
- * word at a time and increase the inner loop count to 32.
- *
- * You can also mix and match the two loop styles, for example doing the
- * bulk of a message byte-at-a-time and adding bit-at-a-time processing
- * for any fractional bytes at the end.
- *
- * The only remaining optimization is to the byte-at-a-time table method.
- * Here, rather than just shifting one bit of the remainder to decide
- * in the correct multiple to subtract, we can shift a byte at a time.
- * This produces a 40-bit (rather than a 33-bit) intermediate remainder,
- * but again the multiple of the polynomial to subtract depends only on
- * the high bits, the high 8 bits in this case.  
- *
- * The multiple we need in that case is the low 32 bits of a 40-bit
- * value whose high 8 bits are given, and which is a multiple of the
- * generator polynomial.  This is simply the CRC-32 of the given
- * one-byte message.
- *
- * Two more details: normally, appending zero bits to a message which
- * is already a multiple of a polynomial produces a larger multiple of that
- * polynomial.  To enable a CRC to detect this condition, it's common to
- * invert the CRC before appending it.  This makes the remainder of the
- * message+crc come out not as zero, but some fixed non-zero value.
- *
- * The same problem applies to zero bits prepended to the message, and
- * a similar solution is used.  Instead of starting with a remainder of
- * 0, an initial remainder of all ones is used.  As long as you start
- * the same way on decoding, it doesn't make a difference.
- */
+#ifdef CONFIG_CRC32_SELFTEST
 
-#ifdef UNITTEST
-
-#include <stdlib.h>
-#include <stdio.h>
+/* 4096 random bytes */
+static u8 __attribute__((__aligned__(8))) test_buf[] =
+{
+	0x5b, 0x85, 0x21, 0xcb, 0x09, 0x68, 0x7d, 0x30,
+	0xc7, 0x69, 0xd7, 0x30, 0x92, 0xde, 0x59, 0xe4,
+	0xc9, 0x6e, 0x8b, 0xdb, 0x98, 0x6b, 0xaa, 0x60,
+	0xa8, 0xb5, 0xbc, 0x6c, 0xa9, 0xb1, 0x5b, 0x2c,
+	0xea, 0xb4, 0x92, 0x6a, 0x3f, 0x79, 0x91, 0xe4,
+	0xe9, 0x70, 0x51, 0x8c, 0x7f, 0x95, 0x6f, 0x1a,
+	0x56, 0xa1, 0x5c, 0x27, 0x03, 0x67, 0x9f, 0x3a,
+	0xe2, 0x31, 0x11, 0x29, 0x6b, 0x98, 0xfc, 0xc4,
+	0x53, 0x24, 0xc5, 0x8b, 0xce, 0x47, 0xb2, 0xb9,
+	0x32, 0xcb, 0xc1, 0xd0, 0x03, 0x57, 0x4e, 0xd4,
+	0xe9, 0x3c, 0xa1, 0x63, 0xcf, 0x12, 0x0e, 0xca,
+	0xe1, 0x13, 0xd1, 0x93, 0xa6, 0x88, 0x5c, 0x61,
+	0x5b, 0xbb, 0xf0, 0x19, 0x46, 0xb4, 0xcf, 0x9e,
+	0xb6, 0x6b, 0x4c, 0x3a, 0xcf, 0x60, 0xf9, 0x7a,
+	0x8d, 0x07, 0x63, 0xdb, 0x40, 0xe9, 0x0b, 0x6f,
+	0xad, 0x97, 0xf1, 0xed, 0xd0, 0x1e, 0x26, 0xfd,
+	0xbf, 0xb7, 0xc8, 0x04, 0x94, 0xf8, 0x8b, 0x8c,
+	0xf1, 0xab, 0x7a, 0xd4, 0xdd, 0xf3, 0xe8, 0x88,
+	0xc3, 0xed, 0x17, 0x8a, 0x9b, 0x40, 0x0d, 0x53,
+	0x62, 0x12, 0x03, 0x5f, 0x1b, 0x35, 0x32, 0x1f,
+	0xb4, 0x7b, 0x93, 0x78, 0x0d, 0xdb, 0xce, 0xa4,
+	0xc0, 0x47, 0xd5, 0xbf, 0x68, 0xe8, 0x5d, 0x74,
+	0x8f, 0x8e, 0x75, 0x1c, 0xb2, 0x4f, 0x9a, 0x60,
+	0xd1, 0xbe, 0x10, 0xf4, 0x5c, 0xa1, 0x53, 0x09,
+	0xa5, 0xe0, 0x09, 0x54, 0x85, 0x5c, 0xdc, 0x07,
+	0xe7, 0x21, 0x69, 0x7b, 0x8a, 0xfd, 0x90, 0xf1,
+	0x22, 0xd0, 0xb4, 0x36, 0x28, 0xe6, 0xb8, 0x0f,
+	0x39, 0xde, 0xc8, 0xf3, 0x86, 0x60, 0x34, 0xd2,
+	0x5e, 0xdf, 0xfd, 0xcf, 0x0f, 0xa9, 0x65, 0xf0,
+	0xd5, 0x4d, 0x96, 0x40, 0xe3, 0xdf, 0x3f, 0x95,
+	0x5a, 0x39, 0x19, 0x93, 0xf4, 0x75, 0xce, 0x22,
+	0x00, 0x1c, 0x93, 0xe2, 0x03, 0x66, 0xf4, 0x93,
+	0x73, 0x86, 0x81, 0x8e, 0x29, 0x44, 0x48, 0x86,
+	0x61, 0x7c, 0x48, 0xa3, 0x43, 0xd2, 0x9c, 0x8d,
+	0xd4, 0x95, 0xdd, 0xe1, 0x22, 0x89, 0x3a, 0x40,
+	0x4c, 0x1b, 0x8a, 0x04, 0xa8, 0x09, 0x69, 0x8b,
+	0xea, 0xc6, 0x55, 0x8e, 0x57, 0xe6, 0x64, 0x35,
+	0xf0, 0xc7, 0x16, 0x9f, 0x5d, 0x5e, 0x86, 0x40,
+	0x46, 0xbb, 0xe5, 0x45, 0x88, 0xfe, 0xc9, 0x63,
+	0x15, 0xfb, 0xf5, 0xbd, 0x71, 0x61, 0xeb, 0x7b,
+	0x78, 0x70, 0x07, 0x31, 0x03, 0x9f, 0xb2, 0xc8,
+	0xa7, 0xab, 0x47, 0xfd, 0xdf, 0xa0, 0x78, 0x72,
+	0xa4, 0x2a, 0xe4, 0xb6, 0xba, 0xc0, 0x1e, 0x86,
+	0x71, 0xe6, 0x3d, 0x18, 0x37, 0x70, 0xe6, 0xff,
+	0xe0, 0xbc, 0x0b, 0x22, 0xa0, 0x1f, 0xd3, 0xed,
+	0xa2, 0x55, 0x39, 0xab, 0xa8, 0x13, 0x73, 0x7c,
+	0x3f, 0xb2, 0xd6, 0x19, 0xac, 0xff, 0x99, 0xed,
+	0xe8, 0xe6, 0xa6, 0x22, 0xe3, 0x9c, 0xf1, 0x30,
+	0xdc, 0x01, 0x0a, 0x56, 0xfa, 0xe4, 0xc9, 0x99,
+	0xdd, 0xa8, 0xd8, 0xda, 0x35, 0x51, 0x73, 0xb4,
+	0x40, 0x86, 0x85, 0xdb, 0x5c, 0xd5, 0x85, 0x80,
+	0x14, 0x9c, 0xfd, 0x98, 0xa9, 0x82, 0xc5, 0x37,
+	0xff, 0x32, 0x5d, 0xd0, 0x0b, 0xfa, 0xdc, 0x04,
+	0x5e, 0x09, 0xd2, 0xca, 0x17, 0x4b, 0x1a, 0x8e,
+	0x15, 0xe1, 0xcc, 0x4e, 0x52, 0x88, 0x35, 0xbd,
+	0x48, 0xfe, 0x15, 0xa0, 0x91, 0xfd, 0x7e, 0x6c,
+	0x0e, 0x5d, 0x79, 0x1b, 0x81, 0x79, 0xd2, 0x09,
+	0x34, 0x70, 0x3d, 0x81, 0xec, 0xf6, 0x24, 0xbb,
+	0xfb, 0xf1, 0x7b, 0xdf, 0x54, 0xea, 0x80, 0x9b,
+	0xc7, 0x99, 0x9e, 0xbd, 0x16, 0x78, 0x12, 0x53,
+	0x5e, 0x01, 0xa7, 0x4e, 0xbd, 0x67, 0xe1, 0x9b,
+	0x4c, 0x0e, 0x61, 0x45, 0x97, 0xd2, 0xf0, 0x0f,
+	0xfe, 0x15, 0x08, 0xb7, 0x11, 0x4c, 0xe7, 0xff,
+	0x81, 0x53, 0xff, 0x91, 0x25, 0x38, 0x7e, 0x40,
+	0x94, 0xe5, 0xe0, 0xad, 0xe6, 0xd9, 0x79, 0xb6,
+	0x92, 0xc9, 0xfc, 0xde, 0xc3, 0x1a, 0x23, 0xbb,
+	0xdd, 0xc8, 0x51, 0x0c, 0x3a, 0x72, 0xfa, 0x73,
+	0x6f, 0xb7, 0xee, 0x61, 0x39, 0x03, 0x01, 0x3f,
+	0x7f, 0x94, 0x2e, 0x2e, 0xba, 0x3a, 0xbb, 0xb4,
+	0xfa, 0x6a, 0x17, 0xfe, 0xea, 0xef, 0x5e, 0x66,
+	0x97, 0x3f, 0x32, 0x3d, 0xd7, 0x3e, 0xb1, 0xf1,
+	0x6c, 0x14, 0x4c, 0xfd, 0x37, 0xd3, 0x38, 0x80,
+	0xfb, 0xde, 0xa6, 0x24, 0x1e, 0xc8, 0xca, 0x7f,
+	0x3a, 0x93, 0xd8, 0x8b, 0x18, 0x13, 0xb2, 0xe5,
+	0xe4, 0x93, 0x05, 0x53, 0x4f, 0x84, 0x66, 0xa7,
+	0x58, 0x5c, 0x7b, 0x86, 0x52, 0x6d, 0x0d, 0xce,
+	0xa4, 0x30, 0x7d, 0xb6, 0x18, 0x9f, 0xeb, 0xff,
+	0x22, 0xbb, 0x72, 0x29, 0xb9, 0x44, 0x0b, 0x48,
+	0x1e, 0x84, 0x71, 0x81, 0xe3, 0x6d, 0x73, 0x26,
+	0x92, 0xb4, 0x4d, 0x2a, 0x29, 0xb8, 0x1f, 0x72,
+	0xed, 0xd0, 0xe1, 0x64, 0x77, 0xea, 0x8e, 0x88,
+	0x0f, 0xef, 0x3f, 0xb1, 0x3b, 0xad, 0xf9, 0xc9,
+	0x8b, 0xd0, 0xac, 0xc6, 0xcc, 0xa9, 0x40, 0xcc,
+	0x76, 0xf6, 0x3b, 0x53, 0xb5, 0x88, 0xcb, 0xc8,
+	0x37, 0xf1, 0xa2, 0xba, 0x23, 0x15, 0x99, 0x09,
+	0xcc, 0xe7, 0x7a, 0x3b, 0x37, 0xf7, 0x58, 0xc8,
+	0x46, 0x8c, 0x2b, 0x2f, 0x4e, 0x0e, 0xa6, 0x5c,
+	0xea, 0x85, 0x55, 0xba, 0x02, 0x0e, 0x0e, 0x48,
+	0xbc, 0xe1, 0xb1, 0x01, 0x35, 0x79, 0x13, 0x3d,
+	0x1b, 0xc0, 0x53, 0x68, 0x11, 0xe7, 0x95, 0x0f,
+	0x9d, 0x3f, 0x4c, 0x47, 0x7b, 0x4d, 0x1c, 0xae,
+	0x50, 0x9b, 0xcb, 0xdd, 0x05, 0x8d, 0x9a, 0x97,
+	0xfd, 0x8c, 0xef, 0x0c, 0x1d, 0x67, 0x73, 0xa8,
+	0x28, 0x36, 0xd5, 0xb6, 0x92, 0x33, 0x40, 0x75,
+	0x0b, 0x51, 0xc3, 0x64, 0xba, 0x1d, 0xc2, 0xcc,
+	0xee, 0x7d, 0x54, 0x0f, 0x27, 0x69, 0xa7, 0x27,
+	0x63, 0x30, 0x29, 0xd9, 0xc8, 0x84, 0xd8, 0xdf,
+	0x9f, 0x68, 0x8d, 0x04, 0xca, 0xa6, 0xc5, 0xc7,
+	0x7a, 0x5c, 0xc8, 0xd1, 0xcb, 0x4a, 0xec, 0xd0,
+	0xd8, 0x20, 0x69, 0xc5, 0x17, 0xcd, 0x78, 0xc8,
+	0x75, 0x23, 0x30, 0x69, 0xc9, 0xd4, 0xea, 0x5c,
+	0x4f, 0x6b, 0x86, 0x3f, 0x8b, 0xfe, 0xee, 0x44,
+	0xc9, 0x7c, 0xb7, 0xdd, 0x3e, 0xe5, 0xec, 0x54,
+	0x03, 0x3e, 0xaa, 0x82, 0xc6, 0xdf, 0xb2, 0x38,
+	0x0e, 0x5d, 0xb3, 0x88, 0xd9, 0xd3, 0x69, 0x5f,
+	0x8f, 0x70, 0x8a, 0x7e, 0x11, 0xd9, 0x1e, 0x7b,
+	0x38, 0xf1, 0x42, 0x1a, 0xc0, 0x35, 0xf5, 0xc7,
+	0x36, 0x85, 0xf5, 0xf7, 0xb8, 0x7e, 0xc7, 0xef,
+	0x18, 0xf1, 0x63, 0xd6, 0x7a, 0xc6, 0xc9, 0x0e,
+	0x4d, 0x69, 0x4f, 0x84, 0xef, 0x26, 0x41, 0x0c,
+	0xec, 0xc7, 0xe0, 0x7e, 0x3c, 0x67, 0x01, 0x4c,
+	0x62, 0x1a, 0x20, 0x6f, 0xee, 0x47, 0x4d, 0xc0,
+	0x99, 0x13, 0x8d, 0x91, 0x4a, 0x26, 0xd4, 0x37,
+	0x28, 0x90, 0x58, 0x75, 0x66, 0x2b, 0x0a, 0xdf,
+	0xda, 0xee, 0x92, 0x25, 0x90, 0x62, 0x39, 0x9e,
+	0x44, 0x98, 0xad, 0xc1, 0x88, 0xed, 0xe4, 0xb4,
+	0xaf, 0xf5, 0x8c, 0x9b, 0x48, 0x4d, 0x56, 0x60,
+	0x97, 0x0f, 0x61, 0x59, 0x9e, 0xa6, 0x27, 0xfe,
+	0xc1, 0x91, 0x15, 0x38, 0xb8, 0x0f, 0xae, 0x61,
+	0x7d, 0x26, 0x13, 0x5a, 0x73, 0xff, 0x1c, 0xa3,
+	0x61, 0x04, 0x58, 0x48, 0x55, 0x44, 0x11, 0xfe,
+	0x15, 0xca, 0xc3, 0xbd, 0xca, 0xc5, 0xb4, 0x40,
+	0x5d, 0x1b, 0x7f, 0x39, 0xb5, 0x9c, 0x35, 0xec,
+	0x61, 0x15, 0x32, 0x32, 0xb8, 0x4e, 0x40, 0x9f,
+	0x17, 0x1f, 0x0a, 0x4d, 0xa9, 0x91, 0xef, 0xb7,
+	0xb0, 0xeb, 0xc2, 0x83, 0x9a, 0x6c, 0xd2, 0x79,
+	0x43, 0x78, 0x5e, 0x2f, 0xe5, 0xdd, 0x1a, 0x3c,
+	0x45, 0xab, 0x29, 0x40, 0x3a, 0x37, 0x5b, 0x6f,
+	0xd7, 0xfc, 0x48, 0x64, 0x3c, 0x49, 0xfb, 0x21,
+	0xbe, 0xc3, 0xff, 0x07, 0xfb, 0x17, 0xe9, 0xc9,
+	0x0c, 0x4c, 0x5c, 0x15, 0x9e, 0x8e, 0x22, 0x30,
+	0x0a, 0xde, 0x48, 0x7f, 0xdb, 0x0d, 0xd1, 0x2b,
+	0x87, 0x38, 0x9e, 0xcc, 0x5a, 0x01, 0x16, 0xee,
+	0x75, 0x49, 0x0d, 0x30, 0x01, 0x34, 0x6a, 0xb6,
+	0x9a, 0x5a, 0x2a, 0xec, 0xbb, 0x48, 0xac, 0xd3,
+	0x77, 0x83, 0xd8, 0x08, 0x86, 0x4f, 0x48, 0x09,
+	0x29, 0x41, 0x79, 0xa1, 0x03, 0x12, 0xc4, 0xcd,
+	0x90, 0x55, 0x47, 0x66, 0x74, 0x9a, 0xcc, 0x4f,
+	0x35, 0x8c, 0xd6, 0x98, 0xef, 0xeb, 0x45, 0xb9,
+	0x9a, 0x26, 0x2f, 0x39, 0xa5, 0x70, 0x6d, 0xfc,
+	0xb4, 0x51, 0xee, 0xf4, 0x9c, 0xe7, 0x38, 0x59,
+	0xad, 0xf4, 0xbc, 0x46, 0xff, 0x46, 0x8e, 0x60,
+	0x9c, 0xa3, 0x60, 0x1d, 0xf8, 0x26, 0x72, 0xf5,
+	0x72, 0x9d, 0x68, 0x80, 0x04, 0xf6, 0x0b, 0xa1,
+	0x0a, 0xd5, 0xa7, 0x82, 0x3a, 0x3e, 0x47, 0xa8,
+	0x5a, 0xde, 0x59, 0x4f, 0x7b, 0x07, 0xb3, 0xe9,
+	0x24, 0x19, 0x3d, 0x34, 0x05, 0xec, 0xf1, 0xab,
+	0x6e, 0x64, 0x8f, 0xd3, 0xe6, 0x41, 0x86, 0x80,
+	0x70, 0xe3, 0x8d, 0x60, 0x9c, 0x34, 0x25, 0x01,
+	0x07, 0x4d, 0x19, 0x41, 0x4e, 0x3d, 0x5c, 0x7e,
+	0xa8, 0xf5, 0xcc, 0xd5, 0x7b, 0xe2, 0x7d, 0x3d,
+	0x49, 0x86, 0x7d, 0x07, 0xb7, 0x10, 0xe3, 0x35,
+	0xb8, 0x84, 0x6d, 0x76, 0xab, 0x17, 0xc6, 0x38,
+	0xb4, 0xd3, 0x28, 0x57, 0xad, 0xd3, 0x88, 0x5a,
+	0xda, 0xea, 0xc8, 0x94, 0xcc, 0x37, 0x19, 0xac,
+	0x9c, 0x9f, 0x4b, 0x00, 0x15, 0xc0, 0xc8, 0xca,
+	0x1f, 0x15, 0xaa, 0xe0, 0xdb, 0xf9, 0x2f, 0x57,
+	0x1b, 0x24, 0xc7, 0x6f, 0x76, 0x29, 0xfb, 0xed,
+	0x25, 0x0d, 0xc0, 0xfe, 0xbd, 0x5a, 0xbf, 0x20,
+	0x08, 0x51, 0x05, 0xec, 0x71, 0xa3, 0xbf, 0xef,
+	0x5e, 0x99, 0x75, 0xdb, 0x3c, 0x5f, 0x9a, 0x8c,
+	0xbb, 0x19, 0x5c, 0x0e, 0x93, 0x19, 0xf8, 0x6a,
+	0xbc, 0xf2, 0x12, 0x54, 0x2f, 0xcb, 0x28, 0x64,
+	0x88, 0xb3, 0x92, 0x0d, 0x96, 0xd1, 0xa6, 0xe4,
+	0x1f, 0xf1, 0x4d, 0xa4, 0xab, 0x1c, 0xee, 0x54,
+	0xf2, 0xad, 0x29, 0x6d, 0x32, 0x37, 0xb2, 0x16,
+	0x77, 0x5c, 0xdc, 0x2e, 0x54, 0xec, 0x75, 0x26,
+	0xc6, 0x36, 0xd9, 0x17, 0x2c, 0xf1, 0x7a, 0xdc,
+	0x4b, 0xf1, 0xe2, 0xd9, 0x95, 0xba, 0xac, 0x87,
+	0xc1, 0xf3, 0x8e, 0x58, 0x08, 0xd8, 0x87, 0x60,
+	0xc9, 0xee, 0x6a, 0xde, 0xa4, 0xd2, 0xfc, 0x0d,
+	0xe5, 0x36, 0xc4, 0x5c, 0x52, 0xb3, 0x07, 0x54,
+	0x65, 0x24, 0xc1, 0xb1, 0xd1, 0xb1, 0x53, 0x13,
+	0x31, 0x79, 0x7f, 0x05, 0x76, 0xeb, 0x37, 0x59,
+	0x15, 0x2b, 0xd1, 0x3f, 0xac, 0x08, 0x97, 0xeb,
+	0x91, 0x98, 0xdf, 0x6c, 0x09, 0x0d, 0x04, 0x9f,
+	0xdc, 0x3b, 0x0e, 0x60, 0x68, 0x47, 0x23, 0x15,
+	0x16, 0xc6, 0x0b, 0x35, 0xf8, 0x77, 0xa2, 0x78,
+	0x50, 0xd4, 0x64, 0x22, 0x33, 0xff, 0xfb, 0x93,
+	0x71, 0x46, 0x50, 0x39, 0x1b, 0x9c, 0xea, 0x4e,
+	0x8d, 0x0c, 0x37, 0xe5, 0x5c, 0x51, 0x3a, 0x31,
+	0xb2, 0x85, 0x84, 0x3f, 0x41, 0xee, 0xa2, 0xc1,
+	0xc6, 0x13, 0x3b, 0x54, 0x28, 0xd2, 0x18, 0x37,
+	0xcc, 0x46, 0x9f, 0x6a, 0x91, 0x3d, 0x5a, 0x15,
+	0x3c, 0x89, 0xa3, 0x61, 0x06, 0x7d, 0x2e, 0x78,
+	0xbe, 0x7d, 0x40, 0xba, 0x2f, 0x95, 0xb1, 0x2f,
+	0x87, 0x3b, 0x8a, 0xbe, 0x6a, 0xf4, 0xc2, 0x31,
+	0x74, 0xee, 0x91, 0xe0, 0x23, 0xaa, 0x5d, 0x7f,
+	0xdd, 0xf0, 0x44, 0x8c, 0x0b, 0x59, 0x2b, 0xfc,
+	0x48, 0x3a, 0xdf, 0x07, 0x05, 0x38, 0x6c, 0xc9,
+	0xeb, 0x18, 0x24, 0x68, 0x8d, 0x58, 0x98, 0xd3,
+	0x31, 0xa3, 0xe4, 0x70, 0x59, 0xb1, 0x21, 0xbe,
+	0x7e, 0x65, 0x7d, 0xb8, 0x04, 0xab, 0xf6, 0xe4,
+	0xd7, 0xda, 0xec, 0x09, 0x8f, 0xda, 0x6d, 0x24,
+	0x07, 0xcc, 0x29, 0x17, 0x05, 0x78, 0x1a, 0xc1,
+	0xb1, 0xce, 0xfc, 0xaa, 0x2d, 0xe7, 0xcc, 0x85,
+	0x84, 0x84, 0x03, 0x2a, 0x0c, 0x3f, 0xa9, 0xf8,
+	0xfd, 0x84, 0x53, 0x59, 0x5c, 0xf0, 0xd4, 0x09,
+	0xf0, 0xd2, 0x6c, 0x32, 0x03, 0xb0, 0xa0, 0x8c,
+	0x52, 0xeb, 0x23, 0x91, 0x88, 0x43, 0x13, 0x46,
+	0xf6, 0x1e, 0xb4, 0x1b, 0xf5, 0x8e, 0x3a, 0xb5,
+	0x3d, 0x00, 0xf6, 0xe5, 0x08, 0x3d, 0x5f, 0x39,
+	0xd3, 0x21, 0x69, 0xbc, 0x03, 0x22, 0x3a, 0xd2,
+	0x5c, 0x84, 0xf8, 0x15, 0xc4, 0x80, 0x0b, 0xbc,
+	0x29, 0x3c, 0xf3, 0x95, 0x98, 0xcd, 0x8f, 0x35,
+	0xbc, 0xa5, 0x3e, 0xfc, 0xd4, 0x13, 0x9e, 0xde,
+	0x4f, 0xce, 0x71, 0x9d, 0x09, 0xad, 0xf2, 0x80,
+	0x6b, 0x65, 0x7f, 0x03, 0x00, 0x14, 0x7c, 0x15,
+	0x85, 0x40, 0x6d, 0x70, 0xea, 0xdc, 0xb3, 0x63,
+	0x35, 0x4f, 0x4d, 0xe0, 0xd9, 0xd5, 0x3c, 0x58,
+	0x56, 0x23, 0x80, 0xe2, 0x36, 0xdd, 0x75, 0x1d,
+	0x94, 0x11, 0x41, 0x8e, 0xe0, 0x81, 0x8e, 0xcf,
+	0xe0, 0xe5, 0xf6, 0xde, 0xd1, 0xe7, 0x04, 0x12,
+	0x79, 0x92, 0x2b, 0x71, 0x2a, 0x79, 0x8b, 0x7c,
+	0x44, 0x79, 0x16, 0x30, 0x4e, 0xf4, 0xf6, 0x9b,
+	0xb7, 0x40, 0xa3, 0x5a, 0xa7, 0x69, 0x3e, 0xc1,
+	0x3a, 0x04, 0xd0, 0x88, 0xa0, 0x3b, 0xdd, 0xc6,
+	0x9e, 0x7e, 0x1e, 0x1e, 0x8f, 0x44, 0xf7, 0x73,
+	0x67, 0x1e, 0x1a, 0x78, 0xfa, 0x62, 0xf4, 0xa9,
+	0xa8, 0xc6, 0x5b, 0xb8, 0xfa, 0x06, 0x7d, 0x5e,
+	0x38, 0x1c, 0x9a, 0x39, 0xe9, 0x39, 0x98, 0x22,
+	0x0b, 0xa7, 0xac, 0x0b, 0xf3, 0xbc, 0xf1, 0xeb,
+	0x8c, 0x81, 0xe3, 0x48, 0x8a, 0xed, 0x42, 0xc2,
+	0x38, 0xcf, 0x3e, 0xda, 0xd2, 0x89, 0x8d, 0x9c,
+	0x53, 0xb5, 0x2f, 0x41, 0x01, 0x26, 0x84, 0x9c,
+	0xa3, 0x56, 0xf6, 0x49, 0xc7, 0xd4, 0x9f, 0x93,
+	0x1b, 0x96, 0x49, 0x5e, 0xad, 0xb3, 0x84, 0x1f,
+	0x3c, 0xa4, 0xe0, 0x9b, 0xd1, 0x90, 0xbc, 0x38,
+	0x6c, 0xdd, 0x95, 0x4d, 0x9d, 0xb1, 0x71, 0x57,
+	0x2d, 0x34, 0xe8, 0xb8, 0x42, 0xc7, 0x99, 0x03,
+	0xc7, 0x07, 0x30, 0x65, 0x91, 0x55, 0xd5, 0x90,
+	0x70, 0x97, 0x37, 0x68, 0xd4, 0x11, 0xf9, 0xe8,
+	0xce, 0xec, 0xdc, 0x34, 0xd5, 0xd3, 0xb7, 0xc4,
+	0xb8, 0x97, 0x05, 0x92, 0xad, 0xf8, 0xe2, 0x36,
+	0x64, 0x41, 0xc9, 0xc5, 0x41, 0x77, 0x52, 0xd7,
+	0x2c, 0xa5, 0x24, 0x2f, 0xd9, 0x34, 0x0b, 0x47,
+	0x35, 0xa7, 0x28, 0x8b, 0xc5, 0xcd, 0xe9, 0x46,
+	0xac, 0x39, 0x94, 0x3c, 0x10, 0xc6, 0x29, 0x73,
+	0x0e, 0x0e, 0x5d, 0xe0, 0x71, 0x03, 0x8a, 0x72,
+	0x0e, 0x26, 0xb0, 0x7d, 0x84, 0xed, 0x95, 0x23,
+	0x49, 0x5a, 0x45, 0x83, 0x45, 0x60, 0x11, 0x4a,
+	0x46, 0x31, 0xd4, 0xd8, 0x16, 0x54, 0x98, 0x58,
+	0xed, 0x6d, 0xcc, 0x5d, 0xd6, 0x50, 0x61, 0x9f,
+	0x9d, 0xc5, 0x3e, 0x9d, 0x32, 0x47, 0xde, 0x96,
+	0xe1, 0x5d, 0xd8, 0xf8, 0xb4, 0x69, 0x6f, 0xb9,
+	0x15, 0x90, 0x57, 0x7a, 0xf6, 0xad, 0xb0, 0x5b,
+	0xf5, 0xa6, 0x36, 0x94, 0xfd, 0x84, 0xce, 0x1c,
+	0x0f, 0x4b, 0xd0, 0xc2, 0x5b, 0x6b, 0x56, 0xef,
+	0x73, 0x93, 0x0b, 0xc3, 0xee, 0xd9, 0xcf, 0xd3,
+	0xa4, 0x22, 0x58, 0xcd, 0x50, 0x6e, 0x65, 0xf4,
+	0xe9, 0xb7, 0x71, 0xaf, 0x4b, 0xb3, 0xb6, 0x2f,
+	0x0f, 0x0e, 0x3b, 0xc9, 0x85, 0x14, 0xf5, 0x17,
+	0xe8, 0x7a, 0x3a, 0xbf, 0x5f, 0x5e, 0xf8, 0x18,
+	0x48, 0xa6, 0x72, 0xab, 0x06, 0x95, 0xe9, 0xc8,
+	0xa7, 0xf4, 0x32, 0x44, 0x04, 0x0c, 0x84, 0x98,
+	0x73, 0xe3, 0x89, 0x8d, 0x5f, 0x7e, 0x4a, 0x42,
+	0x8f, 0xc5, 0x28, 0xb1, 0x82, 0xef, 0x1c, 0x97,
+	0x31, 0x3b, 0x4d, 0xe0, 0x0e, 0x10, 0x10, 0x97,
+	0x93, 0x49, 0x78, 0x2f, 0x0d, 0x86, 0x8b, 0xa1,
+	0x53, 0xa9, 0x81, 0x20, 0x79, 0xe7, 0x07, 0x77,
+	0xb6, 0xac, 0x5e, 0xd2, 0x05, 0xcd, 0xe9, 0xdb,
+	0x8a, 0x94, 0x82, 0x8a, 0x23, 0xb9, 0x3d, 0x1c,
+	0xa9, 0x7d, 0x72, 0x4a, 0xed, 0x33, 0xa3, 0xdb,
+	0x21, 0xa7, 0x86, 0x33, 0x45, 0xa5, 0xaa, 0x56,
+	0x45, 0xb5, 0x83, 0x29, 0x40, 0x47, 0x79, 0x04,
+	0x6e, 0xb9, 0x95, 0xd0, 0x81, 0x77, 0x2d, 0x48,
+	0x1e, 0xfe, 0xc3, 0xc2, 0x1e, 0xe5, 0xf2, 0xbe,
+	0xfd, 0x3b, 0x94, 0x9f, 0xc4, 0xc4, 0x26, 0x9d,
+	0xe4, 0x66, 0x1e, 0x19, 0xee, 0x6c, 0x79, 0x97,
+	0x11, 0x31, 0x4b, 0x0d, 0x01, 0xcb, 0xde, 0xa8,
+	0xf6, 0x6d, 0x7c, 0x39, 0x46, 0x4e, 0x7e, 0x3f,
+	0x94, 0x17, 0xdf, 0xa1, 0x7d, 0xd9, 0x1c, 0x8e,
+	0xbc, 0x7d, 0x33, 0x7d, 0xe3, 0x12, 0x40, 0xca,
+	0xab, 0x37, 0x11, 0x46, 0xd4, 0xae, 0xef, 0x44,
+	0xa2, 0xb3, 0x6a, 0x66, 0x0e, 0x0c, 0x90, 0x7f,
+	0xdf, 0x5c, 0x66, 0x5f, 0xf2, 0x94, 0x9f, 0xa6,
+	0x73, 0x4f, 0xeb, 0x0d, 0xad, 0xbf, 0xc0, 0x63,
+	0x5c, 0xdc, 0x46, 0x51, 0xe8, 0x8e, 0x90, 0x19,
+	0xa8, 0xa4, 0x3c, 0x91, 0x79, 0xfa, 0x7e, 0x58,
+	0x85, 0x13, 0x55, 0xc5, 0x19, 0x82, 0x37, 0x1b,
+	0x0a, 0x02, 0x1f, 0x99, 0x6b, 0x18, 0xf1, 0x28,
+	0x08, 0xa2, 0x73, 0xb8, 0x0f, 0x2e, 0xcd, 0xbf,
+	0xf3, 0x86, 0x7f, 0xea, 0xef, 0xd0, 0xbb, 0xa6,
+	0x21, 0xdf, 0x49, 0x73, 0x51, 0xcc, 0x36, 0xd3,
+	0x3e, 0xa0, 0xf8, 0x44, 0xdf, 0xd3, 0xa6, 0xbe,
+	0x8a, 0xd4, 0x57, 0xdd, 0x72, 0x94, 0x61, 0x0f,
+	0x82, 0xd1, 0x07, 0xb8, 0x7c, 0x18, 0x83, 0xdf,
+	0x3a, 0xe5, 0x50, 0x6a, 0x82, 0x20, 0xac, 0xa9,
+	0xa8, 0xff, 0xd9, 0xf3, 0x77, 0x33, 0x5a, 0x9e,
+	0x7f, 0x6d, 0xfe, 0x5d, 0x33, 0x41, 0x42, 0xe7,
+	0x6c, 0x19, 0xe0, 0x44, 0x8a, 0x15, 0xf6, 0x70,
+	0x98, 0xb7, 0x68, 0x4d, 0xfa, 0x97, 0x39, 0xb0,
+	0x8e, 0xe8, 0x84, 0x8b, 0x75, 0x30, 0xb7, 0x7d,
+	0x92, 0x69, 0x20, 0x9c, 0x81, 0xfb, 0x4b, 0xf4,
+	0x01, 0x50, 0xeb, 0xce, 0x0c, 0x1c, 0x6c, 0xb5,
+	0x4a, 0xd7, 0x27, 0x0c, 0xce, 0xbb, 0xe5, 0x85,
+	0xf0, 0xb6, 0xee, 0xd5, 0x70, 0xdd, 0x3b, 0xfc,
+	0xd4, 0x99, 0xf1, 0x33, 0xdd, 0x8b, 0xc4, 0x2f,
+	0xae, 0xab, 0x74, 0x96, 0x32, 0xc7, 0x4c, 0x56,
+	0x3c, 0x89, 0x0f, 0x96, 0x0b, 0x42, 0xc0, 0xcb,
+	0xee, 0x0f, 0x0b, 0x8c, 0xfb, 0x7e, 0x47, 0x7b,
+	0x64, 0x48, 0xfd, 0xb2, 0x00, 0x80, 0x89, 0xa5,
+	0x13, 0x55, 0x62, 0xfc, 0x8f, 0xe2, 0x42, 0x03,
+	0xb7, 0x4e, 0x2a, 0x79, 0xb4, 0x82, 0xea, 0x23,
+	0x49, 0xda, 0xaf, 0x52, 0x63, 0x1e, 0x60, 0x03,
+	0x89, 0x06, 0x44, 0x46, 0x08, 0xc3, 0xc4, 0x87,
+	0x70, 0x2e, 0xda, 0x94, 0xad, 0x6b, 0xe0, 0xe4,
+	0xd1, 0x8a, 0x06, 0xc2, 0xa8, 0xc0, 0xa7, 0x43,
+	0x3c, 0x47, 0x52, 0x0e, 0xc3, 0x77, 0x81, 0x11,
+	0x67, 0x0e, 0xa0, 0x70, 0x04, 0x47, 0x29, 0x40,
+	0x86, 0x0d, 0x34, 0x56, 0xa7, 0xc9, 0x35, 0x59,
+	0x68, 0xdc, 0x93, 0x81, 0x70, 0xee, 0x86, 0xd9,
+	0x80, 0x06, 0x40, 0x4f, 0x1a, 0x0d, 0x40, 0x30,
+	0x0b, 0xcb, 0x96, 0x47, 0xc1, 0xb7, 0x52, 0xfd,
+	0x56, 0xe0, 0x72, 0x4b, 0xfb, 0xbd, 0x92, 0x45,
+	0x61, 0x71, 0xc2, 0x33, 0x11, 0xbf, 0x52, 0x83,
+	0x79, 0x26, 0xe0, 0x49, 0x6b, 0xb7, 0x05, 0x8b,
+	0xe8, 0x0e, 0x87, 0x31, 0xd7, 0x9d, 0x8a, 0xf5,
+	0xc0, 0x5f, 0x2e, 0x58, 0x4a, 0xdb, 0x11, 0xb3,
+	0x6c, 0x30, 0x2a, 0x46, 0x19, 0xe3, 0x27, 0x84,
+	0x1f, 0x63, 0x6e, 0xf6, 0x57, 0xc7, 0xc9, 0xd8,
+	0x5e, 0xba, 0xb3, 0x87, 0xd5, 0x83, 0x26, 0x34,
+	0x21, 0x9e, 0x65, 0xde, 0x42, 0xd3, 0xbe, 0x7b,
+	0xbc, 0x91, 0x71, 0x44, 0x4d, 0x99, 0x3b, 0x31,
+	0xe5, 0x3f, 0x11, 0x4e, 0x7f, 0x13, 0x51, 0x3b,
+	0xae, 0x79, 0xc9, 0xd3, 0x81, 0x8e, 0x25, 0x40,
+	0x10, 0xfc, 0x07, 0x1e, 0xf9, 0x7b, 0x9a, 0x4b,
+	0x6c, 0xe3, 0xb3, 0xad, 0x1a, 0x0a, 0xdd, 0x9e,
+	0x59, 0x0c, 0xa2, 0xcd, 0xae, 0x48, 0x4a, 0x38,
+	0x5b, 0x47, 0x41, 0x94, 0x65, 0x6b, 0xbb, 0xeb,
+	0x5b, 0xe3, 0xaf, 0x07, 0x5b, 0xd4, 0x4a, 0xa2,
+	0xc9, 0x5d, 0x2f, 0x64, 0x03, 0xd7, 0x3a, 0x2c,
+	0x6e, 0xce, 0x76, 0x95, 0xb4, 0xb3, 0xc0, 0xf1,
+	0xe2, 0x45, 0x73, 0x7a, 0x5c, 0xab, 0xc1, 0xfc,
+	0x02, 0x8d, 0x81, 0x29, 0xb3, 0xac, 0x07, 0xec,
+	0x40, 0x7d, 0x45, 0xd9, 0x7a, 0x59, 0xee, 0x34,
+	0xf0, 0xe9, 0xd5, 0x7b, 0x96, 0xb1, 0x3d, 0x95,
+	0xcc, 0x86, 0xb5, 0xb6, 0x04, 0x2d, 0xb5, 0x92,
+	0x7e, 0x76, 0xf4, 0x06, 0xa9, 0xa3, 0x12, 0x0f,
+	0xb1, 0xaf, 0x26, 0xba, 0x7c, 0xfc, 0x7e, 0x1c,
+	0xbc, 0x2c, 0x49, 0x97, 0x53, 0x60, 0x13, 0x0b,
+	0xa6, 0x61, 0x83, 0x89, 0x42, 0xd4, 0x17, 0x0c,
+	0x6c, 0x26, 0x52, 0xc3, 0xb3, 0xd4, 0x67, 0xf5,
+	0xe3, 0x04, 0xb7, 0xf4, 0xcb, 0x80, 0xb8, 0xcb,
+	0x77, 0x56, 0x3e, 0xaa, 0x57, 0x54, 0xee, 0xb4,
+	0x2c, 0x67, 0xcf, 0xf2, 0xdc, 0xbe, 0x55, 0xf9,
+	0x43, 0x1f, 0x6e, 0x22, 0x97, 0x67, 0x7f, 0xc4,
+	0xef, 0xb1, 0x26, 0x31, 0x1e, 0x27, 0xdf, 0x41,
+	0x80, 0x47, 0x6c, 0xe2, 0xfa, 0xa9, 0x8c, 0x2a,
+	0xf6, 0xf2, 0xab, 0xf0, 0x15, 0xda, 0x6c, 0xc8,
+	0xfe, 0xb5, 0x23, 0xde, 0xa9, 0x05, 0x3f, 0x06,
+	0x54, 0x4c, 0xcd, 0xe1, 0xab, 0xfc, 0x0e, 0x62,
+	0x33, 0x31, 0x73, 0x2c, 0x76, 0xcb, 0xb4, 0x47,
+	0x1e, 0x20, 0xad, 0xd8, 0xf2, 0x31, 0xdd, 0xc4,
+	0x8b, 0x0c, 0x77, 0xbe, 0xe1, 0x8b, 0x26, 0x00,
+	0x02, 0x58, 0xd6, 0x8d, 0xef, 0xad, 0x74, 0x67,
+	0xab, 0x3f, 0xef, 0xcb, 0x6f, 0xb0, 0xcc, 0x81,
+	0x44, 0x4c, 0xaf, 0xe9, 0x49, 0x4f, 0xdb, 0xa0,
+	0x25, 0xa4, 0xf0, 0x89, 0xf1, 0xbe, 0xd8, 0x10,
+	0xff, 0xb1, 0x3b, 0x4b, 0xfa, 0x98, 0xf5, 0x79,
+	0x6d, 0x1e, 0x69, 0x4d, 0x57, 0xb1, 0xc8, 0x19,
+	0x1b, 0xbd, 0x1e, 0x8c, 0x84, 0xb7, 0x7b, 0xe8,
+	0xd2, 0x2d, 0x09, 0x41, 0x41, 0x37, 0x3d, 0xb1,
+	0x6f, 0x26, 0x5d, 0x71, 0x16, 0x3d, 0xb7, 0x83,
+	0x27, 0x2c, 0xa7, 0xb6, 0x50, 0xbd, 0x91, 0x86,
+	0xab, 0x24, 0xa1, 0x38, 0xfd, 0xea, 0x71, 0x55,
+	0x7e, 0x9a, 0x07, 0x77, 0x4b, 0xfa, 0x61, 0x66,
+	0x20, 0x1e, 0x28, 0x95, 0x18, 0x1b, 0xa4, 0xa0,
+	0xfd, 0xc0, 0x89, 0x72, 0x43, 0xd9, 0x3b, 0x49,
+	0x5a, 0x3f, 0x9d, 0xbf, 0xdb, 0xb4, 0x46, 0xea,
+	0x42, 0x01, 0x77, 0x23, 0x68, 0x95, 0xb6, 0x24,
+	0xb3, 0xa8, 0x6c, 0x28, 0x3b, 0x11, 0x40, 0x7e,
+	0x18, 0x65, 0x6d, 0xd8, 0x24, 0x42, 0x7d, 0x88,
+	0xc0, 0x52, 0xd9, 0x05, 0xe4, 0x95, 0x90, 0x87,
+	0x8c, 0xf4, 0xd0, 0x6b, 0xb9, 0x83, 0x99, 0x34,
+	0x6d, 0xfe, 0x54, 0x40, 0x94, 0x52, 0x21, 0x4f,
+	0x14, 0x25, 0xc5, 0xd6, 0x5e, 0x95, 0xdc, 0x0a,
+	0x2b, 0x89, 0x20, 0x11, 0x84, 0x48, 0xd6, 0x3a,
+	0xcd, 0x5c, 0x24, 0xad, 0x62, 0xe3, 0xb1, 0x93,
+	0x25, 0x8d, 0xcd, 0x7e, 0xfc, 0x27, 0xa3, 0x37,
+	0xfd, 0x84, 0xfc, 0x1b, 0xb2, 0xf1, 0x27, 0x38,
+	0x5a, 0xb7, 0xfc, 0xf2, 0xfa, 0x95, 0x66, 0xd4,
+	0xfb, 0xba, 0xa7, 0xd7, 0xa3, 0x72, 0x69, 0x48,
+	0x48, 0x8c, 0xeb, 0x28, 0x89, 0xfe, 0x33, 0x65,
+	0x5a, 0x36, 0x01, 0x7e, 0x06, 0x79, 0x0a, 0x09,
+	0x3b, 0x74, 0x11, 0x9a, 0x6e, 0xbf, 0xd4, 0x9e,
+	0x58, 0x90, 0x49, 0x4f, 0x4d, 0x08, 0xd4, 0xe5,
+	0x4a, 0x09, 0x21, 0xef, 0x8b, 0xb8, 0x74, 0x3b,
+	0x91, 0xdd, 0x36, 0x85, 0x60, 0x2d, 0xfa, 0xd4,
+	0x45, 0x7b, 0x45, 0x53, 0xf5, 0x47, 0x87, 0x7e,
+	0xa6, 0x37, 0xc8, 0x78, 0x7a, 0x68, 0x9d, 0x8d,
+	0x65, 0x2c, 0x0e, 0x91, 0x5c, 0xa2, 0x60, 0xf0,
+	0x8e, 0x3f, 0xe9, 0x1a, 0xcd, 0xaa, 0xe7, 0xd5,
+	0x77, 0x18, 0xaf, 0xc9, 0xbc, 0x18, 0xea, 0x48,
+	0x1b, 0xfb, 0x22, 0x48, 0x70, 0x16, 0x29, 0x9e,
+	0x5b, 0xc1, 0x2c, 0x66, 0x23, 0xbc, 0xf0, 0x1f,
+	0xef, 0xaf, 0xe4, 0xd6, 0x04, 0x19, 0x82, 0x7a,
+	0x0b, 0xba, 0x4b, 0x46, 0xb1, 0x6a, 0x85, 0x5d,
+	0xb4, 0x73, 0xd6, 0x21, 0xa1, 0x71, 0x60, 0x14,
+	0xee, 0x0a, 0x77, 0xc4, 0x66, 0x2e, 0xf9, 0x69,
+	0x30, 0xaf, 0x41, 0x0b, 0xc8, 0x83, 0x3c, 0x53,
+	0x99, 0x19, 0x27, 0x46, 0xf7, 0x41, 0x6e, 0x56,
+	0xdc, 0x94, 0x28, 0x67, 0x4e, 0xb7, 0x25, 0x48,
+	0x8a, 0xc2, 0xe0, 0x60, 0x96, 0xcc, 0x18, 0xf4,
+	0x84, 0xdd, 0xa7, 0x5e, 0x3e, 0x05, 0x0b, 0x26,
+	0x26, 0xb2, 0x5c, 0x1f, 0x57, 0x1a, 0x04, 0x7e,
+	0x6a, 0xe3, 0x2f, 0xb4, 0x35, 0xb6, 0x38, 0x40,
+	0x40, 0xcd, 0x6f, 0x87, 0x2e, 0xef, 0xa3, 0xd7,
+	0xa9, 0xc2, 0xe8, 0x0d, 0x27, 0xdf, 0x44, 0x62,
+	0x99, 0xa0, 0xfc, 0xcf, 0x81, 0x78, 0xcb, 0xfe,
+	0xe5, 0xa0, 0x03, 0x4e, 0x6c, 0xd7, 0xf4, 0xaf,
+	0x7a, 0xbb, 0x61, 0x82, 0xfe, 0x71, 0x89, 0xb2,
+	0x22, 0x7c, 0x8e, 0x83, 0x04, 0xce, 0xf6, 0x5d,
+	0x84, 0x8f, 0x95, 0x6a, 0x7f, 0xad, 0xfd, 0x32,
+	0x9c, 0x5e, 0xe4, 0x9c, 0x89, 0x60, 0x54, 0xaa,
+	0x96, 0x72, 0xd2, 0xd7, 0x36, 0x85, 0xa9, 0x45,
+	0xd2, 0x2a, 0xa1, 0x81, 0x49, 0x6f, 0x7e, 0x04,
+	0xfa, 0xe2, 0xfe, 0x90, 0x26, 0x77, 0x5a, 0x33,
+	0xb8, 0x04, 0x9a, 0x7a, 0xe6, 0x4c, 0x4f, 0xad,
+	0x72, 0x96, 0x08, 0x28, 0x58, 0x13, 0xf8, 0xc4,
+	0x1c, 0xf0, 0xc3, 0x45, 0x95, 0x49, 0x20, 0x8c,
+	0x9f, 0x39, 0x70, 0xe1, 0x77, 0xfe, 0xd5, 0x4b,
+	0xaf, 0x86, 0xda, 0xef, 0x22, 0x06, 0x83, 0x36,
+	0x29, 0x12, 0x11, 0x40, 0xbc, 0x3b, 0x86, 0xaa,
+	0xaa, 0x65, 0x60, 0xc3, 0x80, 0xca, 0xed, 0xa9,
+	0xf3, 0xb0, 0x79, 0x96, 0xa2, 0x55, 0x27, 0x28,
+	0x55, 0x73, 0x26, 0xa5, 0x50, 0xea, 0x92, 0x4b,
+	0x3c, 0x5c, 0x82, 0x33, 0xf0, 0x01, 0x3f, 0x03,
+	0xc1, 0x08, 0x05, 0xbf, 0x98, 0xf4, 0x9b, 0x6d,
+	0xa5, 0xa8, 0xb4, 0x82, 0x0c, 0x06, 0xfa, 0xff,
+	0x2d, 0x08, 0xf3, 0x05, 0x4f, 0x57, 0x2a, 0x39,
+	0xd4, 0x83, 0x0d, 0x75, 0x51, 0xd8, 0x5b, 0x1b,
+	0xd3, 0x51, 0x5a, 0x32, 0x2a, 0x9b, 0x32, 0xb2,
+	0xf2, 0xa4, 0x96, 0x12, 0xf2, 0xae, 0x40, 0x34,
+	0x67, 0xa8, 0xf5, 0x44, 0xd5, 0x35, 0x53, 0xfe,
+	0xa3, 0x60, 0x96, 0x63, 0x0f, 0x1f, 0x6e, 0xb0,
+	0x5a, 0x42, 0xa6, 0xfc, 0x51, 0x0b, 0x60, 0x27,
+	0xbc, 0x06, 0x71, 0xed, 0x65, 0x5b, 0x23, 0x86,
+	0x4a, 0x07, 0x3b, 0x22, 0x07, 0x46, 0xe6, 0x90,
+	0x3e, 0xf3, 0x25, 0x50, 0x1b, 0x4c, 0x7f, 0x03,
+	0x08, 0xa8, 0x36, 0x6b, 0x87, 0xe5, 0xe3, 0xdb,
+	0x9a, 0x38, 0x83, 0xff, 0x9f, 0x1a, 0x9f, 0x57,
+	0xa4, 0x2a, 0xf6, 0x37, 0xbc, 0x1a, 0xff, 0xc9,
+	0x1e, 0x35, 0x0c, 0xc3, 0x7c, 0xa3, 0xb2, 0xe5,
+	0xd2, 0xc6, 0xb4, 0x57, 0x47, 0xe4, 0x32, 0x16,
+	0x6d, 0xa9, 0xae, 0x64, 0xe6, 0x2d, 0x8d, 0xc5,
+	0x8d, 0x50, 0x8e, 0xe8, 0x1a, 0x22, 0x34, 0x2a,
+	0xd9, 0xeb, 0x51, 0x90, 0x4a, 0xb1, 0x41, 0x7d,
+	0x64, 0xf9, 0xb9, 0x0d, 0xf6, 0x23, 0x33, 0xb0,
+	0x33, 0xf4, 0xf7, 0x3f, 0x27, 0x84, 0xc6, 0x0f,
+	0x54, 0xa5, 0xc0, 0x2e, 0xec, 0x0b, 0x3a, 0x48,
+	0x6e, 0x80, 0x35, 0x81, 0x43, 0x9b, 0x90, 0xb1,
+	0xd0, 0x2b, 0xea, 0x21, 0xdc, 0xda, 0x5b, 0x09,
+	0xf4, 0xcc, 0x10, 0xb4, 0xc7, 0xfe, 0x79, 0x51,
+	0xc3, 0xc5, 0xac, 0x88, 0x74, 0x84, 0x0b, 0x4b,
+	0xca, 0x79, 0x16, 0x29, 0xfb, 0x69, 0x54, 0xdf,
+	0x41, 0x7e, 0xe9, 0xc7, 0x8e, 0xea, 0xa5, 0xfe,
+	0xfc, 0x76, 0x0e, 0x90, 0xc4, 0x92, 0x38, 0xad,
+	0x7b, 0x48, 0xe6, 0x6e, 0xf7, 0x21, 0xfd, 0x4e,
+	0x93, 0x0a, 0x7b, 0x41, 0x83, 0x68, 0xfb, 0x57,
+	0x51, 0x76, 0x34, 0xa9, 0x6c, 0x00, 0xaa, 0x4f,
+	0x66, 0x65, 0x98, 0x4a, 0x4f, 0xa3, 0xa0, 0xef,
+	0x69, 0x3f, 0xe3, 0x1c, 0x92, 0x8c, 0xfd, 0xd8,
+	0xe8, 0xde, 0x7c, 0x7f, 0x3e, 0x84, 0x8e, 0x69,
+	0x3c, 0xf1, 0xf2, 0x05, 0x46, 0xdc, 0x2f, 0x9d,
+	0x5e, 0x6e, 0x4c, 0xfb, 0xb5, 0x99, 0x2a, 0x59,
+	0x63, 0xc1, 0x34, 0xbc, 0x57, 0xc0, 0x0d, 0xb9,
+	0x61, 0x25, 0xf3, 0x33, 0x23, 0x51, 0xb6, 0x0d,
+	0x07, 0xa6, 0xab, 0x94, 0x4a, 0xb7, 0x2a, 0xea,
+	0xee, 0xac, 0xa3, 0xc3, 0x04, 0x8b, 0x0e, 0x56,
+	0xfe, 0x44, 0xa7, 0x39, 0xe2, 0xed, 0xed, 0xb4,
+	0x22, 0x2b, 0xac, 0x12, 0x32, 0x28, 0x91, 0xd8,
+	0xa5, 0xab, 0xff, 0x5f, 0xe0, 0x4b, 0xda, 0x78,
+	0x17, 0xda, 0xf1, 0x01, 0x5b, 0xcd, 0xe2, 0x5f,
+	0x50, 0x45, 0x73, 0x2b, 0xe4, 0x76, 0x77, 0xf4,
+	0x64, 0x1d, 0x43, 0xfb, 0x84, 0x7a, 0xea, 0x91,
+	0xae, 0xf9, 0x9e, 0xb7, 0xb4, 0xb0, 0x91, 0x5f,
+	0x16, 0x35, 0x9a, 0x11, 0xb8, 0xc7, 0xc1, 0x8c,
+	0xc6, 0x10, 0x8d, 0x2f, 0x63, 0x4a, 0xa7, 0x57,
+	0x3a, 0x51, 0xd6, 0x32, 0x2d, 0x64, 0x72, 0xd4,
+	0x66, 0xdc, 0x10, 0xa6, 0x67, 0xd6, 0x04, 0x23,
+	0x9d, 0x0a, 0x11, 0x77, 0xdd, 0x37, 0x94, 0x17,
+	0x3c, 0xbf, 0x8b, 0x65, 0xb0, 0x2e, 0x5e, 0x66,
+	0x47, 0x64, 0xac, 0xdd, 0xf0, 0x84, 0xfd, 0x39,
+	0xfa, 0x15, 0x5d, 0xef, 0xae, 0xca, 0xc1, 0x36,
+	0xa7, 0x5c, 0xbf, 0xc7, 0x08, 0xc2, 0x66, 0x00,
+	0x74, 0x74, 0x4e, 0x27, 0x3f, 0x55, 0x8a, 0xb7,
+	0x38, 0x66, 0x83, 0x6d, 0xcf, 0x99, 0x9e, 0x60,
+	0x8f, 0xdd, 0x2e, 0x62, 0x22, 0x0e, 0xef, 0x0c,
+	0x98, 0xa7, 0x85, 0x74, 0x3b, 0x9d, 0xec, 0x9e,
+	0xa9, 0x19, 0x72, 0xa5, 0x7f, 0x2c, 0x39, 0xb7,
+	0x7d, 0xb7, 0xf1, 0x12, 0x65, 0x27, 0x4b, 0x5a,
+	0xde, 0x17, 0xfe, 0xad, 0x44, 0xf3, 0x20, 0x4d,
+	0xfd, 0xe4, 0x1f, 0xb5, 0x81, 0xb0, 0x36, 0x37,
+	0x08, 0x6f, 0xc3, 0x0c, 0xe9, 0x85, 0x98, 0x82,
+	0xa9, 0x62, 0x0c, 0xc4, 0x97, 0xc0, 0x50, 0xc8,
+	0xa7, 0x3c, 0x50, 0x9f, 0x43, 0xb9, 0xcd, 0x5e,
+	0x4d, 0xfa, 0x1c, 0x4b, 0x0b, 0xa9, 0x98, 0x85,
+	0x38, 0x92, 0xac, 0x8d, 0xe4, 0xad, 0x9b, 0x98,
+	0xab, 0xd9, 0x38, 0xac, 0x62, 0x52, 0xa3, 0x22,
+	0x63, 0x0f, 0xbf, 0x95, 0x48, 0xdf, 0x69, 0xe7,
+	0x8b, 0x33, 0xd5, 0xb2, 0xbd, 0x05, 0x49, 0x49,
+	0x9d, 0x57, 0x73, 0x19, 0x33, 0xae, 0xfa, 0x33,
+	0xf1, 0x19, 0xa8, 0x80, 0xce, 0x04, 0x9f, 0xbc,
+	0x1d, 0x65, 0x82, 0x1b, 0xe5, 0x3a, 0x51, 0xc8,
+	0x1c, 0x21, 0xe3, 0x5d, 0xf3, 0x7d, 0x9b, 0x2f,
+	0x2c, 0x1d, 0x4a, 0x7f, 0x9b, 0x68, 0x35, 0xa3,
+	0xb2, 0x50, 0xf7, 0x62, 0x79, 0xcd, 0xf4, 0x98,
+	0x4f, 0xe5, 0x63, 0x7c, 0x3e, 0x45, 0x31, 0x8c,
+	0x16, 0xa0, 0x12, 0xc8, 0x58, 0xce, 0x39, 0xa6,
+	0xbc, 0x54, 0xdb, 0xc5, 0xe0, 0xd5, 0xba, 0xbc,
+	0xb9, 0x04, 0xf4, 0x8d, 0xe8, 0x2f, 0x15, 0x9d,
+};
 
-#if 0				/*Not used at present */
-static void
-buf_dump(char const *prefix, unsigned char const *buf, size_t len)
+/* 100 test cases */
+static struct crc_test {
+	u32 crc;	/* random starting crc */
+	u32 start;	/* random 6 bit offset in buf */
+	u32 length;	/* random 11 bit length of test */
+	u32 crc_le;	/* expected crc32_le result */
+	u32 crc_be;	/* expected crc32_be result */
+	u32 crc32c_le;	/* expected crc32c_le result */
+} test[] =
 {
-	fputs(prefix, stdout);
-	while (len--)
-		printf(" %02x", *buf++);
-	putchar('\n');
+	{0x674bf11d, 0x00000038, 0x00000542, 0x0af6d466, 0xd8b6e4c1,
+	 0xf6e93d6c},
+	{0x35c672c6, 0x0000003a, 0x000001aa, 0xc6d3dfba, 0x28aaf3ad,
+	 0x0fe92aca},
+	{0x496da28e, 0x00000039, 0x000005af, 0xd933660f, 0x5d57e81f,
+	 0x52e1ebb8},
+	{0x09a9b90e, 0x00000027, 0x000001f8, 0xb45fe007, 0xf45fca9a,
+	 0x0798af9a},
+	{0xdc97e5a9, 0x00000025, 0x000003b6, 0xf81a3562, 0xe0126ba2,
+	 0x18eb3152},
+	{0x47c58900, 0x0000000a, 0x000000b9, 0x8e58eccf, 0xf3afc793,
+	 0xd00d08c7},
+	{0x292561e8, 0x0000000c, 0x00000403, 0xa2ba8aaf, 0x0b797aed,
+	 0x8ba966bc},
+	{0x415037f6, 0x00000003, 0x00000676, 0xa17d52e8, 0x7f0fdf35,
+	 0x11d694a2},
+	{0x3466e707, 0x00000026, 0x00000042, 0x258319be, 0x75c484a2,
+	 0x6ab3208d},
+	{0xafd1281b, 0x00000023, 0x000002ee, 0x4428eaf8, 0x06c7ad10,
+	 0xba4603c5},
+	{0xd3857b18, 0x00000028, 0x000004a2, 0x5c430821, 0xb062b7cb,
+	 0xe6071c6f},
+	{0x1d825a8f, 0x0000002b, 0x0000050b, 0xd2c45f0c, 0xd68634e0,
+	 0x179ec30a},
+	{0x5033e3bc, 0x0000000b, 0x00000078, 0xa3ea4113, 0xac6d31fb,
+	 0x0903beb8},
+	{0x94f1fb5e, 0x0000000f, 0x000003a2, 0xfbfc50b1, 0x3cfe50ed,
+	 0x6a7cb4fa},
+	{0xc9a0fe14, 0x00000009, 0x00000473, 0x5fb61894, 0x87070591,
+	 0xdb535801},
+	{0x88a034b1, 0x0000001c, 0x000005ad, 0xc1b16053, 0x46f95c67,
+	 0x92bed597},
+	{0xf0f72239, 0x00000020, 0x0000026d, 0xa6fa58f3, 0xf8c2c1dd,
+	 0x192a3f1b},
+	{0xcc20a5e3, 0x0000003b, 0x0000067a, 0x7740185a, 0x308b979a,
+	 0xccbaec1a},
+	{0xce589c95, 0x0000002b, 0x00000641, 0xd055e987, 0x40aae25b,
+	 0x7eabae4d},
+	{0x78edc885, 0x00000035, 0x000005be, 0xa39cb14b, 0x035b0d1f,
+	 0x28c72982},
+	{0x9d40a377, 0x0000003b, 0x00000038, 0x1f47ccd2, 0x197fbc9d,
+	 0xc3cd4d18},
+	{0x703d0e01, 0x0000003c, 0x000006f1, 0x88735e7c, 0xfed57c5a,
+	 0xbca8f0e7},
+	{0x776bf505, 0x0000000f, 0x000005b2, 0x5cc4fc01, 0xf32efb97,
+	 0x713f60b3},
+	{0x4a3e7854, 0x00000027, 0x000004b8, 0x8d923c82, 0x0cbfb4a2,
+	 0xebd08fd5},
+	{0x209172dd, 0x0000003b, 0x00000356, 0xb89e9c2b, 0xd7868138,
+	 0x64406c59},
+	{0x3ba4cc5b, 0x0000002f, 0x00000203, 0xe51601a9, 0x5b2a1032,
+	 0x7421890e},
+	{0xfc62f297, 0x00000000, 0x00000079, 0x71a8e1a2, 0x5d88685f,
+	 0xe9347603},
+	{0x64280b8b, 0x00000016, 0x000007ab, 0x0fa7a30c, 0xda3a455f,
+	 0x1bef9060},
+	{0x97dd724b, 0x00000033, 0x000007ad, 0x5788b2f4, 0xd7326d32,
+	 0x34720072},
+	{0x61394b52, 0x00000035, 0x00000571, 0xc66525f1, 0xcabe7fef,
+	 0x48310f59},
+	{0x29b4faff, 0x00000024, 0x0000006e, 0xca13751e, 0x993648e0,
+	 0x783a4213},
+	{0x29bfb1dc, 0x0000000b, 0x00000244, 0x436c43f7, 0x429f7a59,
+	 0x9e8efd41},
+	{0x86ae934b, 0x00000035, 0x00000104, 0x0760ec93, 0x9cf7d0f4,
+	 0xfc3d34a5},
+	{0xc4c1024e, 0x0000002e, 0x000006b1, 0x6516a3ec, 0x19321f9c,
+	 0x17a52ae2},
+	{0x3287a80a, 0x00000026, 0x00000496, 0x0b257eb1, 0x754ebd51,
+	 0x886d935a},
+	{0xa4db423e, 0x00000023, 0x0000045d, 0x9b3a66dc, 0x873e9f11,
+	 0xeaaeaeb2},
+	{0x7a1078df, 0x00000015, 0x0000014a, 0x8c2484c5, 0x6a628659,
+	 0x8e900a4b},
+	{0x6048bd5b, 0x00000006, 0x0000006a, 0x897e3559, 0xac9961af,
+	 0xd74662b1},
+	{0xd8f9ea20, 0x0000003d, 0x00000277, 0x60eb905b, 0xed2aaf99,
+	 0xd26752ba},
+	{0xea5ec3b4, 0x0000002a, 0x000004fe, 0x869965dc, 0x6c1f833b,
+	 0x8b1fcd62},
+	{0x2dfb005d, 0x00000016, 0x00000345, 0x6a3b117e, 0xf05e8521,
+	 0xf54342fe},
+	{0x5a214ade, 0x00000020, 0x000005b6, 0x467f70be, 0xcb22ccd3,
+	 0x5b95b988},
+	{0xf0ab9cca, 0x00000032, 0x00000515, 0xed223df3, 0x7f3ef01d,
+	 0x2e1176be},
+	{0x91b444f9, 0x0000002e, 0x000007f8, 0x84e9a983, 0x5676756f,
+	 0x66120546},
+	{0x1b5d2ddb, 0x0000002e, 0x0000012c, 0xba638c4c, 0x3f42047b,
+	 0xf256a5cc},
+	{0xd824d1bb, 0x0000003a, 0x000007b5, 0x6288653b, 0x3a3ebea0,
+	 0x4af1dd69},
+	{0x0470180c, 0x00000034, 0x000001f0, 0x9d5b80d6, 0x3de08195,
+	 0x56f0a04a},
+	{0xffaa3a3f, 0x00000036, 0x00000299, 0xf3a82ab8, 0x53e0c13d,
+	 0x74f6b6b2},
+	{0x6406cfeb, 0x00000023, 0x00000600, 0xa920b8e8, 0xe4e2acf4,
+	 0x085951fd},
+	{0xb24aaa38, 0x0000003e, 0x000004a1, 0x657cc328, 0x5077b2c3,
+	 0xc65387eb},
+	{0x58b2ab7c, 0x00000039, 0x000002b4, 0x3a17ee7e, 0x9dcb3643,
+	 0x1ca9257b},
+	{0x3db85970, 0x00000006, 0x000002b6, 0x95268b59, 0xb9812c10,
+	 0xfd196d76},
+	{0x857830c5, 0x00000003, 0x00000590, 0x4ef439d5, 0xf042161d,
+	 0x5ef88339},
+	{0xe1fcd978, 0x0000003e, 0x000007d8, 0xae8d8699, 0xce0a1ef5,
+	 0x2c3714d9},
+	{0xb982a768, 0x00000016, 0x000006e0, 0x62fad3df, 0x5f8a067b,
+	 0x58576548},
+	{0x1d581ce8, 0x0000001e, 0x0000058b, 0xf0f5da53, 0x26e39eee,
+	 0xfd7c57de},
+	{0x2456719b, 0x00000025, 0x00000503, 0x4296ac64, 0xd50e4c14,
+	 0xd5fedd59},
+	{0xfae6d8f2, 0x00000000, 0x0000055d, 0x057fdf2e, 0x2a31391a,
+	 0x1cc3b17b},
+	{0xcba828e3, 0x00000039, 0x000002ce, 0xe3f22351, 0x8f00877b,
+	 0x270eed73},
+	{0x13d25952, 0x0000000a, 0x0000072d, 0x76d4b4cc, 0x5eb67ec3,
+	 0x91ecbb11},
+	{0x0342be3f, 0x00000015, 0x00000599, 0xec75d9f1, 0x9d4d2826,
+	 0x05ed8d0c},
+	{0xeaa344e0, 0x00000014, 0x000004d8, 0x72a4c981, 0x2064ea06,
+	 0x0b09ad5b},
+	{0xbbb52021, 0x0000003b, 0x00000272, 0x04af99fc, 0xaf042d35,
+	 0xf8d511fb},
+	{0xb66384dc, 0x0000001d, 0x000007fc, 0xd7629116, 0x782bd801,
+	 0x5ad832cc},
+	{0x616c01b6, 0x00000022, 0x000002c8, 0x5b1dab30, 0x783ce7d2,
+	 0x1214d196},
+	{0xce2bdaad, 0x00000016, 0x0000062a, 0x932535c8, 0x3f02926d,
+	 0x5747218a},
+	{0x00fe84d7, 0x00000005, 0x00000205, 0x850e50aa, 0x753d649c,
+	 0xde8f14de},
+	{0xbebdcb4c, 0x00000006, 0x0000055d, 0xbeaa37a2, 0x2d8c9eba,
+	 0x3563b7b9},
+	{0xd8b1a02a, 0x00000010, 0x00000387, 0x5017d2fc, 0x503541a5,
+	 0x071475d0},
+	{0x3b96cad2, 0x00000036, 0x00000347, 0x1d2372ae, 0x926cd90b,
+	 0x54c79d60},
+	{0xc94c1ed7, 0x00000005, 0x0000038b, 0x9e9fdb22, 0x144a9178,
+	 0x4c53eee6},
+	{0x1aad454e, 0x00000025, 0x000002b2, 0xc3f6315c, 0x5c7a35b3,
+	 0x10137a3c},
+	{0xa4fec9a6, 0x00000000, 0x000006d6, 0x90be5080, 0xa4107605,
+	 0xaa9d6c73},
+	{0x1bbe71e2, 0x0000001f, 0x000002fd, 0x4e504c3b, 0x284ccaf1,
+	 0xb63d23e7},
+	{0x4201c7e4, 0x00000002, 0x000002b7, 0x7822e3f9, 0x0cc912a9,
+	 0x7f53e9cf},
+	{0x23fddc96, 0x00000003, 0x00000627, 0x8a385125, 0x07767e78,
+	 0x13c1cd83},
+	{0xd82ba25c, 0x00000016, 0x0000063e, 0x98e4148a, 0x283330c9,
+	 0x49ff5867},
+	{0x786f2032, 0x0000002d, 0x0000060f, 0xf201600a, 0xf561bfcd,
+	 0x8467f211},
+	{0xfebe4e1f, 0x0000002a, 0x000004f2, 0x95e51961, 0xfd80dcab,
+	 0x3f9683b2},
+	{0x1a6e0a39, 0x00000008, 0x00000672, 0x8af6c2a5, 0x78dd84cb,
+	 0x76a3f874},
+	{0x56000ab8, 0x0000000e, 0x000000e5, 0x36bacb8f, 0x22ee1f77,
+	 0x863b702f},
+	{0x4717fe0c, 0x00000000, 0x000006ec, 0x8439f342, 0x5c8e03da,
+	 0xdc6c58ff},
+	{0xd5d5d68e, 0x0000003c, 0x000003a3, 0x46fff083, 0x177d1b39,
+	 0x0622cc95},
+	{0xc25dd6c6, 0x00000024, 0x000006c0, 0x5ceb8eb4, 0x892b0d16,
+	 0xe85605cd},
+	{0xe9b11300, 0x00000023, 0x00000683, 0x07a5d59a, 0x6c6a3208,
+	 0x31da5f06},
+	{0x95cd285e, 0x00000001, 0x00000047, 0x7b3a4368, 0x0202c07e,
+	 0xa1f2e784},
+	{0xd9245a25, 0x0000001e, 0x000003a6, 0xd33c1841, 0x1936c0d5,
+	 0xb07cc616},
+	{0x103279db, 0x00000006, 0x0000039b, 0xca09b8a0, 0x77d62892,
+	 0xbf943b6c},
+	{0x1cba3172, 0x00000027, 0x000001c8, 0xcb377194, 0xebe682db,
+	 0x2c01af1c},
+	{0x8f613739, 0x0000000c, 0x000001df, 0xb4b0bc87, 0x7710bd43,
+	 0x0fe5f56d},
+	{0x1c6aa90d, 0x0000001b, 0x0000053c, 0x70559245, 0xda7894ac,
+	 0xf8943b2d},
+	{0xaabe5b93, 0x0000003d, 0x00000715, 0xcdbf42fa, 0x0c3b99e7,
+	 0xe4d89272},
+	{0xf15dd038, 0x00000006, 0x000006db, 0x6e104aea, 0x8d5967f2,
+	 0x7c2f6bbb},
+	{0x584dd49c, 0x00000020, 0x000007bc, 0x36b6cfd6, 0xad4e23b2,
+	 0xabbf388b},
+	{0x5d8c9506, 0x00000020, 0x00000470, 0x4c62378e, 0x31d92640,
+	 0x1dca1f4e},
+	{0xb80d17b0, 0x00000032, 0x00000346, 0x22a5bb88, 0x9a7ec89f,
+	 0x5c170e23},
+	{0xdaf0592e, 0x00000023, 0x000007b0, 0x3cab3f99, 0x9b1fdd99,
+	 0xc0e9d672},
+	{0x4793cc85, 0x0000000d, 0x00000706, 0xe82e04f6, 0xed3db6b7,
+	 0xc18bdc86},
+	{0x82ebf64e, 0x00000009, 0x000007c3, 0x69d590a9, 0x9efa8499,
+	 0xa874fcdd},
+	{0xb18a0319, 0x00000026, 0x000007db, 0x1cf98dcc, 0x8fa9ad6a,
+	 0x9dc0bb48},
+};
 
-}
-#endif
+#include <linux/time.h>
 
-static void bytereverse(unsigned char *buf, size_t len)
+static int __init crc32c_test(void)
 {
-	while (len--) {
-		unsigned char x = bitrev8(*buf);
-		*buf++ = x;
+	int i;
+	int errors = 0;
+	int bytes = 0;
+	struct timespec start, stop;
+	u64 nsec;
+	unsigned long flags;
+
+	/* keep static to prevent cache warming code from
+	 * getting eliminated by the compiler */
+	static u32 crc;
+
+	/* pre-warm the cache */
+	for (i = 0; i < 100; i++) {
+		bytes += 2*test[i].length;
+
+		crc ^= __crc32c_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length);
 	}
-}
 
-static void random_garbage(unsigned char *buf, size_t len)
-{
-	while (len--)
-		*buf++ = (unsigned char) random();
-}
+	/* reduce OS noise */
+	local_irq_save(flags);
+	local_irq_disable();
 
-#if 0				/* Not used at present */
-static void store_le(u32 x, unsigned char *buf)
-{
-	buf[0] = (unsigned char) x;
-	buf[1] = (unsigned char) (x >> 8);
-	buf[2] = (unsigned char) (x >> 16);
-	buf[3] = (unsigned char) (x >> 24);
-}
-#endif
+	getnstimeofday(&start);
+	for (i = 0; i < 100; i++) {
+		if (test[i].crc32c_le != __crc32c_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length))
+			errors++;
+	}
+	getnstimeofday(&stop);
 
-static void store_be(u32 x, unsigned char *buf)
-{
-	buf[0] = (unsigned char) (x >> 24);
-	buf[1] = (unsigned char) (x >> 16);
-	buf[2] = (unsigned char) (x >> 8);
-	buf[3] = (unsigned char) x;
+	local_irq_restore(flags);
+	local_irq_enable();
+
+	nsec = stop.tv_nsec - start.tv_nsec +
+		1000000000 * (stop.tv_sec - start.tv_sec);
+
+	pr_info("crc32c: CRC_LE_BITS = %d\n", CRC_LE_BITS);
+
+	if (errors)
+		pr_warn("crc32c: %d self tests failed\n", errors);
+	else {
+		pr_info("crc32c: self tests passed, processed %d bytes in %lld nsec\n",
+			bytes, nsec);
+	}
+
+	return 0;
 }
 
-/*
- * This checks that CRC(buf + CRC(buf)) = 0, and that
- * CRC commutes with bit-reversal.  This has the side effect
- * of bytewise bit-reversing the input buffer, and returns
- * the CRC of the reversed buffer.
- */
-static u32 test_step(u32 init, unsigned char *buf, size_t len)
+static int __init crc32_test(void)
 {
-	u32 crc1, crc2;
-	size_t i;
+	int i;
+	int errors = 0;
+	int bytes = 0;
+	struct timespec start, stop;
+	u64 nsec;
+	unsigned long flags;
+
+	/* keep static to prevent cache warming code from
+	 * getting eliminated by the compiler */
+	static u32 crc;
+
+	/* pre-warm the cache */
+	for (i = 0; i < 100; i++) {
+		bytes += 2*test[i].length;
 
-	crc1 = crc32_be(init, buf, len);
-	store_be(crc1, buf + len);
-	crc2 = crc32_be(init, buf, len + 4);
-	if (crc2)
-		printf("\nCRC cancellation fail: 0x%08x should be 0\n",
-		       crc2);
-
-	for (i = 0; i <= len + 4; i++) {
-		crc2 = crc32_be(init, buf, i);
-		crc2 = crc32_be(crc2, buf + i, len + 4 - i);
-		if (crc2)
-			printf("\nCRC split fail: 0x%08x\n", crc2);
+		crc ^= crc32_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length);
+
+		crc ^= crc32_be(test[i].crc, test_buf +
+		    test[i].start, test[i].length);
 	}
 
-	/* Now swap it around for the other test */
-
-	bytereverse(buf, len + 4);
-	init = bitrev32(init);
-	crc2 = bitrev32(crc1);
-	if (crc1 != bitrev32(crc2))
-		printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n",
-		       crc1, crc2, bitrev32(crc2));
-	crc1 = crc32_le(init, buf, len);
-	if (crc1 != crc2)
-		printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1,
-		       crc2);
-	crc2 = crc32_le(init, buf, len + 4);
-	if (crc2)
-		printf("\nCRC cancellation fail: 0x%08x should be 0\n",
-		       crc2);
-
-	for (i = 0; i <= len + 4; i++) {
-		crc2 = crc32_le(init, buf, i);
-		crc2 = crc32_le(crc2, buf + i, len + 4 - i);
-		if (crc2)
-			printf("\nCRC split fail: 0x%08x\n", crc2);
+	/* reduce OS noise */
+	local_irq_save(flags);
+	local_irq_disable();
+
+	getnstimeofday(&start);
+	for (i = 0; i < 100; i++) {
+		if (test[i].crc_le != crc32_le(test[i].crc, test_buf +
+		    test[i].start, test[i].length))
+			errors++;
+
+		if (test[i].crc_be != crc32_be(test[i].crc, test_buf +
+		    test[i].start, test[i].length))
+			errors++;
 	}
+	getnstimeofday(&stop);
 
-	return crc1;
-}
+	local_irq_restore(flags);
+	local_irq_enable();
 
-#define SIZE 64
-#define INIT1 0
-#define INIT2 0
+	nsec = stop.tv_nsec - start.tv_nsec +
+		1000000000 * (stop.tv_sec - start.tv_sec);
 
-int main(void)
-{
-	unsigned char buf1[SIZE + 4];
-	unsigned char buf2[SIZE + 4];
-	unsigned char buf3[SIZE + 4];
-	int i, j;
-	u32 crc1, crc2, crc3;
-
-	for (i = 0; i <= SIZE; i++) {
-		printf("\rTesting length %d...", i);
-		fflush(stdout);
-		random_garbage(buf1, i);
-		random_garbage(buf2, i);
-		for (j = 0; j < i; j++)
-			buf3[j] = buf1[j] ^ buf2[j];
-
-		crc1 = test_step(INIT1, buf1, i);
-		crc2 = test_step(INIT2, buf2, i);
-		/* Now check that CRC(buf1 ^ buf2) = CRC(buf1) ^ CRC(buf2) */
-		crc3 = test_step(INIT1 ^ INIT2, buf3, i);
-		if (crc3 != (crc1 ^ crc2))
-			printf("CRC XOR fail: 0x%08x != 0x%08x ^ 0x%08x\n",
-			       crc3, crc1, crc2);
+	pr_info("crc32: CRC_LE_BITS = %d, CRC_BE BITS = %d\n",
+		 CRC_LE_BITS, CRC_BE_BITS);
+
+	if (errors)
+		pr_warn("crc32: %d self tests failed\n", errors);
+	else {
+		pr_info("crc32: self tests passed, processed %d bytes in %lld nsec\n",
+			bytes, nsec);
 	}
-	printf("\nAll test complete.  No failures expected.\n");
+
+	return 0;
+}
+
+static int __init crc32test_init(void)
+{
+	crc32_test();
+	crc32c_test();
 	return 0;
 }
 
-#endif				/* UNITTEST */
+static void __exit crc32_exit(void)
+{
+}
+
+module_init(crc32test_init);
+module_exit(crc32_exit);
+#endif /* CONFIG_CRC32_SELFTEST */
diff --git a/lib/crc32defs.h b/lib/crc32defs.h
index 9b6773d..64cba2c 100644
--- a/lib/crc32defs.h
+++ b/lib/crc32defs.h
@@ -6,27 +6,67 @@
 #define CRCPOLY_LE 0xedb88320
 #define CRCPOLY_BE 0x04c11db7
 
-/* How many bits at a time to use.  Requires a table of 4<<CRC_xx_BITS bytes. */
-/* For less performance-sensitive, use 4 */
-#ifndef CRC_LE_BITS 
+/*
+ * This is the CRC32c polynomial, as outlined by Castagnoli.
+ * x^32+x^28+x^27+x^26+x^25+x^23+x^22+x^20+x^19+x^18+x^14+x^13+x^11+x^10+x^9+
+ * x^8+x^6+x^0
+ */
+#define CRC32C_POLY_LE 0x82F63B78
+
+/* Try to choose an implementation variant via Kconfig */
+#ifdef CONFIG_CRC32_SLICEBY8
+# define CRC_LE_BITS 64
+# define CRC_BE_BITS 64
+#endif
+#ifdef CONFIG_CRC32_SLICEBY4
+# define CRC_LE_BITS 32
+# define CRC_BE_BITS 32
+#endif
+#ifdef CONFIG_CRC32_SARWATE
 # define CRC_LE_BITS 8
+# define CRC_BE_BITS 8
+#endif
+#ifdef CONFIG_CRC32_BIT
+# define CRC_LE_BITS 1
+# define CRC_BE_BITS 1
+#endif
+
+/*
+ * How many bits at a time to use.  Valid values are 1, 2, 4, 8, 32 and 64.
+ * For less performance-sensitive, use 4 or 8 to save table size.
+ * For larger systems choose same as CPU architecture as default.
+ * This works well on X86_64, SPARC64 systems. This may require some
+ * elaboration after experiments with other architectures.
+ */
+#ifndef CRC_LE_BITS
+#  ifdef CONFIG_64BIT
+#  define CRC_LE_BITS 64
+#  else
+#  define CRC_LE_BITS 32
+#  endif
 #endif
 #ifndef CRC_BE_BITS
-# define CRC_BE_BITS 8
+#  ifdef CONFIG_64BIT
+#  define CRC_BE_BITS 64
+#  else
+#  define CRC_BE_BITS 32
+#  endif
 #endif
 
 /*
  * Little-endian CRC computation.  Used with serial bit streams sent
  * lsbit-first.  Be sure to use cpu_to_le32() to append the computed CRC.
  */
-#if CRC_LE_BITS > 8 || CRC_LE_BITS < 1 || CRC_LE_BITS & CRC_LE_BITS-1
-# error CRC_LE_BITS must be a power of 2 between 1 and 8
+#if CRC_LE_BITS > 64 || CRC_LE_BITS < 1 || CRC_LE_BITS == 16 || \
+	CRC_LE_BITS & CRC_LE_BITS-1
+# error "CRC_LE_BITS must be one of {1, 2, 4, 8, 32, 64}"
 #endif
 
 /*
  * Big-endian CRC computation.  Used with serial bit streams sent
  * msbit-first.  Be sure to use cpu_to_be32() to append the computed CRC.
  */
-#if CRC_BE_BITS > 8 || CRC_BE_BITS < 1 || CRC_BE_BITS & CRC_BE_BITS-1
-# error CRC_BE_BITS must be a power of 2 between 1 and 8
+#if CRC_BE_BITS > 64 || CRC_BE_BITS < 1 || CRC_BE_BITS == 16 || \
+	CRC_BE_BITS & CRC_BE_BITS-1
+# error "CRC_BE_BITS must be one of {1, 2, 4, 8, 32, 64}"
 #endif
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 77cb245..0ab9ae8 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -818,17 +818,9 @@ static int __init fixup_activate(void *addr, enum debug_obj_state state)
 		if (obj->static_init == 1) {
 			debug_object_init(obj, &descr_type_test);
 			debug_object_activate(obj, &descr_type_test);
-			/*
-			 * Real code should return 0 here ! This is
-			 * not a fixup of some bad behaviour. We
-			 * merily call the debug_init function to keep
-			 * track of the object.
-			 */
-			return 1;
-		} else {
-			/* Real code needs to emit a warning here */
+			return 0;
 		}
-		return 0;
+		return 1;
 
 	case ODEBUG_STATE_ACTIVE:
 		debug_object_deactivate(obj, &descr_type_test);
@@ -967,7 +959,7 @@ static void __init debug_objects_selftest(void)
 
 	obj.static_init = 1;
 	debug_object_activate(&obj, &descr_type_test);
-	if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, warnings))
+	if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
 		goto out;
 	debug_object_init(&obj, &descr_type_test);
 	if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings))
diff --git a/lib/gen_crc32table.c b/lib/gen_crc32table.c
index 85d0e41..8f8d543 100644
--- a/lib/gen_crc32table.c
+++ b/lib/gen_crc32table.c
@@ -1,14 +1,29 @@
 #include <stdio.h>
+#include "../include/generated/autoconf.h"
 #include "crc32defs.h"
 #include <inttypes.h>
 
 #define ENTRIES_PER_LINE 4
 
-#define LE_TABLE_SIZE (1 << CRC_LE_BITS)
-#define BE_TABLE_SIZE (1 << CRC_BE_BITS)
+#if CRC_LE_BITS > 8
+# define LE_TABLE_ROWS (CRC_LE_BITS/8)
+# define LE_TABLE_SIZE 256
+#else
+# define LE_TABLE_ROWS 1
+# define LE_TABLE_SIZE (1 << CRC_LE_BITS)
+#endif
 
-static uint32_t crc32table_le[4][LE_TABLE_SIZE];
-static uint32_t crc32table_be[4][BE_TABLE_SIZE];
+#if CRC_BE_BITS > 8
+# define BE_TABLE_ROWS (CRC_BE_BITS/8)
+# define BE_TABLE_SIZE 256
+#else
+# define BE_TABLE_ROWS 1
+# define BE_TABLE_SIZE (1 << CRC_BE_BITS)
+#endif
+
+static uint32_t crc32table_le[LE_TABLE_ROWS][256];
+static uint32_t crc32table_be[BE_TABLE_ROWS][256];
+static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
 
 /**
  * crc32init_le() - allocate and initialize LE table data
@@ -17,27 +32,38 @@ static uint32_t crc32table_be[4][BE_TABLE_SIZE];
  * fact that crctable[i^j] = crctable[i] ^ crctable[j].
  *
  */
-static void crc32init_le(void)
+static void crc32init_le_generic(const uint32_t polynomial,
+				 uint32_t (*tab)[256])
 {
 	unsigned i, j;
 	uint32_t crc = 1;
 
-	crc32table_le[0][0] = 0;
+	tab[0][0] = 0;
 
-	for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) {
-		crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
+	for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) {
+		crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
 		for (j = 0; j < LE_TABLE_SIZE; j += 2 * i)
-			crc32table_le[0][i + j] = crc ^ crc32table_le[0][j];
+			tab[0][i + j] = crc ^ tab[0][j];
 	}
 	for (i = 0; i < LE_TABLE_SIZE; i++) {
-		crc = crc32table_le[0][i];
-		for (j = 1; j < 4; j++) {
-			crc = crc32table_le[0][crc & 0xff] ^ (crc >> 8);
-			crc32table_le[j][i] = crc;
+		crc = tab[0][i];
+		for (j = 1; j < LE_TABLE_ROWS; j++) {
+			crc = tab[0][crc & 0xff] ^ (crc >> 8);
+			tab[j][i] = crc;
 		}
 	}
 }
 
+static void crc32init_le(void)
+{
+	crc32init_le_generic(CRCPOLY_LE, crc32table_le);
+}
+
+static void crc32cinit_le(void)
+{
+	crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le);
+}
+
 /**
  * crc32init_be() - allocate and initialize BE table data
  */
@@ -55,18 +81,18 @@ static void crc32init_be(void)
 	}
 	for (i = 0; i < BE_TABLE_SIZE; i++) {
 		crc = crc32table_be[0][i];
-		for (j = 1; j < 4; j++) {
+		for (j = 1; j < BE_TABLE_ROWS; j++) {
 			crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8);
 			crc32table_be[j][i] = crc;
 		}
 	}
 }
 
-static void output_table(uint32_t table[4][256], int len, char *trans)
+static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
 {
 	int i, j;
 
-	for (j = 0 ; j < 4; j++) {
+	for (j = 0 ; j < rows; j++) {
 		printf("{");
 		for (i = 0; i < len - 1; i++) {
 			if (i % ENTRIES_PER_LINE == 0)
@@ -83,15 +109,30 @@ int main(int argc, char** argv)
 
 	if (CRC_LE_BITS > 1) {
 		crc32init_le();
-		printf("static const u32 crc32table_le[4][256] = {");
-		output_table(crc32table_le, LE_TABLE_SIZE, "tole");
+		printf("static const u32 __cacheline_aligned "
+		       "crc32table_le[%d][%d] = {",
+		       LE_TABLE_ROWS, LE_TABLE_SIZE);
+		output_table(crc32table_le, LE_TABLE_ROWS,
+			     LE_TABLE_SIZE, "tole");
 		printf("};\n");
 	}
 
 	if (CRC_BE_BITS > 1) {
 		crc32init_be();
-		printf("static const u32 crc32table_be[4][256] = {");
-		output_table(crc32table_be, BE_TABLE_SIZE, "tobe");
+		printf("static const u32 __cacheline_aligned "
+		       "crc32table_be[%d][%d] = {",
+		       BE_TABLE_ROWS, BE_TABLE_SIZE);
+		output_table(crc32table_be, LE_TABLE_ROWS,
+			     BE_TABLE_SIZE, "tobe");
+		printf("};\n");
+	}
+	if (CRC_LE_BITS > 1) {
+		crc32cinit_le();
+		printf("static const u32 __cacheline_aligned "
+		       "crc32ctable_le[%d][%d] = {",
+		       LE_TABLE_ROWS, LE_TABLE_SIZE);
+		output_table(crc32ctable_le, LE_TABLE_ROWS,
+			     LE_TABLE_SIZE, "tole");
 		printf("};\n");
 	}
 
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 4ceb05d..33b2cbb 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -390,7 +390,7 @@ bool sg_miter_next(struct sg_mapping_iter *miter)
 	miter->consumed = miter->length;
 
 	if (miter->__flags & SG_MITER_ATOMIC)
-		miter->addr = kmap_atomic(miter->page, KM_BIO_SRC_IRQ) + off;
+		miter->addr = kmap_atomic(miter->page) + off;
 	else
 		miter->addr = kmap(miter->page) + off;
 
@@ -424,7 +424,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
 
 		if (miter->__flags & SG_MITER_ATOMIC) {
 			WARN_ON(!irqs_disabled());
-			kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
+			kunmap_atomic(miter->addr);
 		} else
 			kunmap(miter->page);
 
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 058935e..d0f6315 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -349,13 +349,12 @@ void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
 			sz = min_t(size_t, PAGE_SIZE - offset, size);
 
 			local_irq_save(flags);
-			buffer = kmap_atomic(pfn_to_page(pfn),
-					     KM_BOUNCE_READ);
+			buffer = kmap_atomic(pfn_to_page(pfn));
 			if (dir == DMA_TO_DEVICE)
 				memcpy(dma_addr, buffer + offset, sz);
 			else
 				memcpy(buffer + offset, dma_addr, sz);
-			kunmap_atomic(buffer, KM_BOUNCE_READ);
+			kunmap_atomic(buffer);
 			local_irq_restore(flags);
 
 			size -= sz;
diff --git a/localversion-next b/localversion-next
new file mode 100644
index 0000000..f8c2ee6
--- /dev/null
+++ b/localversion-next
@@ -0,0 +1 @@
+-next-20120120
diff --git a/mm/bounce.c b/mm/bounce.c
index 4e9ae72..d1be02c 100644
--- a/mm/bounce.c
+++ b/mm/bounce.c
@@ -50,9 +50,9 @@ static void bounce_copy_vec(struct bio_vec *to, unsigned char *vfrom)
 	unsigned char *vto;
 
 	local_irq_save(flags);
-	vto = kmap_atomic(to->bv_page, KM_BOUNCE_READ);
+	vto = kmap_atomic(to->bv_page);
 	memcpy(vto + to->bv_offset, vfrom, to->bv_len);
-	kunmap_atomic(vto, KM_BOUNCE_READ);
+	kunmap_atomic(vto);
 	local_irq_restore(flags);
 }
 
diff --git a/mm/filemap.c b/mm/filemap.c
index 97f49ed..8f80345 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1318,10 +1318,10 @@ int file_read_actor(read_descriptor_t *desc, struct page *page,
 	 * taking the kmap.
 	 */
 	if (!fault_in_pages_writeable(desc->arg.buf, size)) {
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		left = __copy_to_user_inatomic(desc->arg.buf,
 						kaddr + offset, size);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		if (left == 0)
 			goto success;
 	}
@@ -2045,7 +2045,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
 	size_t copied;
 
 	BUG_ON(!in_atomic());
-	kaddr = kmap_atomic(page, KM_USER0);
+	kaddr = kmap_atomic(page);
 	if (likely(i->nr_segs == 1)) {
 		int left;
 		char __user *buf = i->iov->iov_base + i->iov_offset;
@@ -2055,7 +2055,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page,
 		copied = __iovec_copy_from_user_inatomic(kaddr + offset,
 						i->iov, i->iov_offset, bytes);
 	}
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 
 	return copied;
 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ea8c3a4..5f34bd8 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2508,6 +2508,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
 {
 	struct hstate *h = hstate_vma(vma);
 	int ret = VM_FAULT_SIGBUS;
+	int anon_rmap = 0;
 	pgoff_t idx;
 	unsigned long size;
 	struct page *page;
@@ -2562,14 +2563,13 @@ retry:
 			spin_lock(&inode->i_lock);
 			inode->i_blocks += blocks_per_huge_page(h);
 			spin_unlock(&inode->i_lock);
-			page_dup_rmap(page);
 		} else {
 			lock_page(page);
 			if (unlikely(anon_vma_prepare(vma))) {
 				ret = VM_FAULT_OOM;
 				goto backout_unlocked;
 			}
-			hugepage_add_new_anon_rmap(page, vma, address);
+			anon_rmap = 1;
 		}
 	} else {
 		/*
@@ -2582,7 +2582,6 @@ retry:
 			      VM_FAULT_SET_HINDEX(h - hstates);
 			goto backout_unlocked;
 		}
-		page_dup_rmap(page);
 	}
 
 	/*
@@ -2606,6 +2605,10 @@ retry:
 	if (!huge_pte_none(huge_ptep_get(ptep)))
 		goto backout;
 
+	if (anon_rmap)
+		hugepage_add_new_anon_rmap(page, vma, address);
+	else
+		page_dup_rmap(page);
 	new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE)
 				&& (vma->vm_flags & VM_SHARED)));
 	set_huge_pte_at(mm, address, ptep, new_pte);
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index c833add..f9f7310 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1036,7 +1036,7 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
 {
 	pr_debug("%s(0x%p)\n", __func__, ptr);
 
-	if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+	if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))
 		add_scan_area((unsigned long)ptr, size, gfp);
 	else if (atomic_read(&kmemleak_early_log))
 		log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
diff --git a/mm/ksm.c b/mm/ksm.c
index 1925ffb..e20de58 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -673,9 +673,9 @@ error:
 static u32 calc_checksum(struct page *page)
 {
 	u32 checksum;
-	void *addr = kmap_atomic(page, KM_USER0);
+	void *addr = kmap_atomic(page);
 	checksum = jhash2(addr, PAGE_SIZE / 4, 17);
-	kunmap_atomic(addr, KM_USER0);
+	kunmap_atomic(addr);
 	return checksum;
 }
 
@@ -684,11 +684,11 @@ static int memcmp_pages(struct page *page1, struct page *page2)
 	char *addr1, *addr2;
 	int ret;
 
-	addr1 = kmap_atomic(page1, KM_USER0);
-	addr2 = kmap_atomic(page2, KM_USER1);
+	addr1 = kmap_atomic(page1);
+	addr2 = kmap_atomic(page2);
 	ret = memcmp(addr1, addr2, PAGE_SIZE);
-	kunmap_atomic(addr2, KM_USER1);
-	kunmap_atomic(addr1, KM_USER0);
+	kunmap_atomic(addr2);
+	kunmap_atomic(addr1);
 	return ret;
 }
 
diff --git a/mm/memblock.c b/mm/memblock.c
index 2f55f19..77b5f22 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -106,14 +106,17 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
 	if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
 		end = memblock.current_limit;
 
-	/* adjust @start to avoid underflow and allocating the first page */
-	start = max3(start, size, (phys_addr_t)PAGE_SIZE);
+	/* avoid allocating the first page */
+	start = max_t(phys_addr_t, start, PAGE_SIZE);
 	end = max(start, end);
 
 	for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
 		this_start = clamp(this_start, start, end);
 		this_end = clamp(this_end, start, end);
 
+		if (this_end < size)
+			continue;
+
 		cand = round_down(this_end - size, align);
 		if (cand >= this_start)
 			return cand;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3dbff4d..32923f2 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -135,7 +135,7 @@ struct mem_cgroup_reclaim_iter {
  */
 struct mem_cgroup_per_zone {
 	struct lruvec		lruvec;
-	unsigned long		count[NR_LRU_LISTS];
+	unsigned long		lru_size[NR_LRU_LISTS];
 
 	struct mem_cgroup_reclaim_iter reclaim_iter[DEF_PRIORITY + 1];
 
@@ -144,11 +144,9 @@ struct mem_cgroup_per_zone {
 	unsigned long long	usage_in_excess;/* Set to the value by which */
 						/* the soft limit is exceeded*/
 	bool			on_tree;
-	struct mem_cgroup	*mem;		/* Back pointer, we cannot */
+	struct mem_cgroup	*memcg;		/* Back pointer, we cannot */
 						/* use container_of	   */
 };
-/* Macro for accessing counter */
-#define MEM_CGROUP_ZSTAT(mz, idx)	((mz)->count[(idx)])
 
 struct mem_cgroup_per_node {
 	struct mem_cgroup_per_zone zoneinfo[MAX_NR_ZONES];
@@ -592,9 +590,9 @@ retry:
 	 * we will to add it back at the end of reclaim to its correct
 	 * position in the tree.
 	 */
-	__mem_cgroup_remove_exceeded(mz->mem, mz, mctz);
-	if (!res_counter_soft_limit_excess(&mz->mem->res) ||
-		!css_tryget(&mz->mem->css))
+	__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;
@@ -701,14 +699,14 @@ mem_cgroup_zone_nr_lru_pages(struct mem_cgroup *memcg, int nid, int zid,
 			unsigned int lru_mask)
 {
 	struct mem_cgroup_per_zone *mz;
-	enum lru_list l;
+	enum lru_list lru;
 	unsigned long ret = 0;
 
 	mz = mem_cgroup_zoneinfo(memcg, nid, zid);
 
-	for_each_lru(l) {
-		if (BIT(l) & lru_mask)
-			ret += MEM_CGROUP_ZSTAT(mz, l);
+	for_each_lru(lru) {
+		if (BIT(lru) & lru_mask)
+			ret += mz->lru_size[lru];
 	}
 	return ret;
 }
@@ -1043,7 +1041,7 @@ struct lruvec *mem_cgroup_lru_add_list(struct zone *zone, struct page *page,
 	memcg = pc->mem_cgroup;
 	mz = page_cgroup_zoneinfo(memcg, page);
 	/* compound_order() is stabilized through lru_lock */
-	MEM_CGROUP_ZSTAT(mz, lru) += 1 << compound_order(page);
+	mz->lru_size[lru] += 1 << compound_order(page);
 	return &mz->lruvec;
 }
 
@@ -1071,8 +1069,8 @@ void mem_cgroup_lru_del_list(struct page *page, enum lru_list lru)
 	VM_BUG_ON(!memcg);
 	mz = page_cgroup_zoneinfo(memcg, page);
 	/* huge page split is done under lru_lock. so, we have no races. */
-	VM_BUG_ON(MEM_CGROUP_ZSTAT(mz, lru) < (1 << compound_order(page)));
-	MEM_CGROUP_ZSTAT(mz, lru) -= 1 << compound_order(page);
+	VM_BUG_ON(mz->lru_size[lru] < (1 << compound_order(page)));
+	mz->lru_size[lru] -= 1 << compound_order(page);
 }
 
 void mem_cgroup_lru_del(struct page *page)
@@ -1359,7 +1357,6 @@ void mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 	if (!memcg || !p)
 		return;
 
-
 	rcu_read_lock();
 
 	mem_cgrp = memcg->css.cgroup;
@@ -1738,22 +1735,22 @@ static DEFINE_SPINLOCK(memcg_oom_lock);
 static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
 
 struct oom_wait_info {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	wait_queue_t	wait;
 };
 
 static int memcg_oom_wake_function(wait_queue_t *wait,
 	unsigned mode, int sync, void *arg)
 {
-	struct mem_cgroup *wake_memcg = (struct mem_cgroup *)arg,
-			  *oom_wait_memcg;
+	struct mem_cgroup *wake_memcg = (struct mem_cgroup *)arg;
+	struct mem_cgroup *oom_wait_memcg;
 	struct oom_wait_info *oom_wait_info;
 
 	oom_wait_info = container_of(wait, struct oom_wait_info, wait);
-	oom_wait_memcg = oom_wait_info->mem;
+	oom_wait_memcg = oom_wait_info->memcg;
 
 	/*
-	 * Both of oom_wait_info->mem and wake_mem are stable under us.
+	 * Both of oom_wait_info->memcg and wake_memcg are stable under us.
 	 * Then we can use css_is_ancestor without taking care of RCU.
 	 */
 	if (!mem_cgroup_same_or_subtree(oom_wait_memcg, wake_memcg)
@@ -1782,7 +1779,7 @@ bool mem_cgroup_handle_oom(struct mem_cgroup *memcg, gfp_t mask)
 	struct oom_wait_info owait;
 	bool locked, need_to_kill;
 
-	owait.mem = memcg;
+	owait.memcg = memcg;
 	owait.wait.flags = 0;
 	owait.wait.func = memcg_oom_wake_function;
 	owait.wait.private = current;
@@ -1894,7 +1891,6 @@ out:
 	if (unlikely(need_unlock))
 		move_unlock_page_cgroup(pc, &flags);
 	rcu_read_unlock();
-	return;
 }
 EXPORT_SYMBOL(mem_cgroup_update_page_stat);
 
@@ -2688,7 +2684,6 @@ __mem_cgroup_commit_charge_lrucare(struct page *page, struct mem_cgroup *memcg,
 		SetPageLRU(page);
 	}
 	spin_unlock_irqrestore(&zone->lru_lock, flags);
-	return;
 }
 
 int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
@@ -2878,7 +2873,6 @@ direct_uncharge:
 		res_counter_uncharge(&memcg->memsw, nr_pages * PAGE_SIZE);
 	if (unlikely(batch->memcg != memcg))
 		memcg_oom_recover(memcg);
-	return;
 }
 
 /*
@@ -3247,7 +3241,7 @@ int mem_cgroup_prepare_migration(struct page *page,
 		ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
 	else
 		ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
-	__mem_cgroup_commit_charge(memcg, page, 1, pc, ctype);
+	__mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype);
 	return ret;
 }
 
@@ -3530,7 +3524,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 			break;
 
 		nr_scanned = 0;
-		reclaimed = mem_cgroup_soft_reclaim(mz->mem, zone,
+		reclaimed = mem_cgroup_soft_reclaim(mz->memcg, zone,
 						    gfp_mask, &nr_scanned);
 		nr_reclaimed += reclaimed;
 		*total_scanned += nr_scanned;
@@ -3557,13 +3551,13 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 				next_mz =
 				__mem_cgroup_largest_soft_limit_node(mctz);
 				if (next_mz == mz)
-					css_put(&next_mz->mem->css);
+					css_put(&next_mz->memcg->css);
 				else /* next_mz == NULL or other memcg */
 					break;
 			} while (1);
 		}
-		__mem_cgroup_remove_exceeded(mz->mem, mz, mctz);
-		excess = res_counter_soft_limit_excess(&mz->mem->res);
+		__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.
@@ -3573,9 +3567,9 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 		 * term TODO.
 		 */
 		/* If excess == 0, no tree ops */
-		__mem_cgroup_insert_exceeded(mz->mem, mz, mctz, excess);
+		__mem_cgroup_insert_exceeded(mz->memcg, mz, mctz, excess);
 		spin_unlock(&mctz->lock);
-		css_put(&mz->mem->css);
+		css_put(&mz->memcg->css);
 		loop++;
 		/*
 		 * Could not reclaim anything and there are no more
@@ -3588,7 +3582,7 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 			break;
 	} while (!nr_reclaimed);
 	if (next_mz)
-		css_put(&next_mz->mem->css);
+		css_put(&next_mz->memcg->css);
 	return nr_reclaimed;
 }
 
@@ -3610,7 +3604,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 	mz = mem_cgroup_zoneinfo(memcg, node, zid);
 	list = &mz->lruvec.lists[lru];
 
-	loop = MEM_CGROUP_ZSTAT(mz, lru);
+	loop = mz->lru_size[lru];
 	/* give some margin against EBUSY etc...*/
 	loop += 256;
 	busy = NULL;
@@ -3684,10 +3678,10 @@ move_account:
 		mem_cgroup_start_move(memcg);
 		for_each_node_state(node, N_HIGH_MEMORY) {
 			for (zid = 0; !ret && zid < MAX_NR_ZONES; zid++) {
-				enum lru_list l;
-				for_each_lru(l) {
+				enum lru_list lru;
+				for_each_lru(lru) {
 					ret = mem_cgroup_force_empty_list(memcg,
-							node, zid, l);
+							node, zid, lru);
 					if (ret)
 						break;
 				}
@@ -3920,7 +3914,6 @@ static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg,
 out:
 	*mem_limit = min_limit;
 	*memsw_limit = min_memsw_limit;
-	return;
 }
 
 static int mem_cgroup_reset(struct cgroup *cont, unsigned int event)
@@ -4079,38 +4072,38 @@ static int mem_control_numa_stat_show(struct seq_file *m, void *arg)
 	unsigned long total_nr, file_nr, anon_nr, unevictable_nr;
 	unsigned long node_nr;
 	struct cgroup *cont = m->private;
-	struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 
-	total_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL);
+	total_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL);
 	seq_printf(m, "total=%lu", total_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid, LRU_ALL);
+		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid, LRU_ALL);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	file_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_FILE);
+	file_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_FILE);
 	seq_printf(m, "file=%lu", file_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				LRU_ALL_FILE);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	anon_nr = mem_cgroup_nr_lru_pages(mem_cont, LRU_ALL_ANON);
+	anon_nr = mem_cgroup_nr_lru_pages(memcg, LRU_ALL_ANON);
 	seq_printf(m, "anon=%lu", anon_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				LRU_ALL_ANON);
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
 	seq_putc(m, '\n');
 
-	unevictable_nr = mem_cgroup_nr_lru_pages(mem_cont, BIT(LRU_UNEVICTABLE));
+	unevictable_nr = mem_cgroup_nr_lru_pages(memcg, BIT(LRU_UNEVICTABLE));
 	seq_printf(m, "unevictable=%lu", unevictable_nr);
 	for_each_node_state(nid, N_HIGH_MEMORY) {
-		node_nr = mem_cgroup_node_nr_lru_pages(mem_cont, nid,
+		node_nr = mem_cgroup_node_nr_lru_pages(memcg, nid,
 				BIT(LRU_UNEVICTABLE));
 		seq_printf(m, " N%d=%lu", nid, node_nr);
 	}
@@ -4122,12 +4115,12 @@ static int mem_control_numa_stat_show(struct seq_file *m, void *arg)
 static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
 				 struct cgroup_map_cb *cb)
 {
-	struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont);
+	struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
 	struct mcs_total_stat mystat;
 	int i;
 
 	memset(&mystat, 0, sizeof(mystat));
-	mem_cgroup_get_local_stat(mem_cont, &mystat);
+	mem_cgroup_get_local_stat(memcg, &mystat);
 
 
 	for (i = 0; i < NR_MCS_STAT; i++) {
@@ -4139,14 +4132,14 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
 	/* Hierarchical information */
 	{
 		unsigned long long limit, memsw_limit;
-		memcg_get_hierarchical_limit(mem_cont, &limit, &memsw_limit);
+		memcg_get_hierarchical_limit(memcg, &limit, &memsw_limit);
 		cb->fill(cb, "hierarchical_memory_limit", limit);
 		if (do_swap_account)
 			cb->fill(cb, "hierarchical_memsw_limit", memsw_limit);
 	}
 
 	memset(&mystat, 0, sizeof(mystat));
-	mem_cgroup_get_total_stat(mem_cont, &mystat);
+	mem_cgroup_get_total_stat(memcg, &mystat);
 	for (i = 0; i < NR_MCS_STAT; i++) {
 		if (i == MCS_SWAP && !do_swap_account)
 			continue;
@@ -4162,7 +4155,7 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
 
 		for_each_online_node(nid)
 			for (zid = 0; zid < MAX_NR_ZONES; zid++) {
-				mz = mem_cgroup_zoneinfo(mem_cont, nid, zid);
+				mz = mem_cgroup_zoneinfo(memcg, nid, zid);
 
 				recent_rotated[0] +=
 					mz->reclaim_stat.recent_rotated[0];
@@ -4716,7 +4709,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 {
 	struct mem_cgroup_per_node *pn;
 	struct mem_cgroup_per_zone *mz;
-	enum lru_list l;
+	enum lru_list lru;
 	int zone, tmp = node;
 	/*
 	 * This routine is called against possible nodes.
@@ -4734,11 +4727,11 @@ 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];
-		for_each_lru(l)
-			INIT_LIST_HEAD(&mz->lruvec.lists[l]);
+		for_each_lru(lru)
+			INIT_LIST_HEAD(&mz->lruvec.lists[lru]);
 		mz->usage_in_excess = 0;
 		mz->on_tree = false;
-		mz->mem = memcg;
+		mz->memcg = memcg;
 	}
 	memcg->info.nodeinfo[node] = pn;
 	return 0;
@@ -4751,29 +4744,29 @@ static void free_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 
 static struct mem_cgroup *mem_cgroup_alloc(void)
 {
-	struct mem_cgroup *mem;
+	struct mem_cgroup *memcg;
 	int size = sizeof(struct mem_cgroup);
 
 	/* Can be very big if MAX_NUMNODES is very big */
 	if (size < PAGE_SIZE)
-		mem = kzalloc(size, GFP_KERNEL);
+		memcg = kzalloc(size, GFP_KERNEL);
 	else
-		mem = vzalloc(size);
+		memcg = vzalloc(size);
 
-	if (!mem)
+	if (!memcg)
 		return NULL;
 
-	mem->stat = alloc_percpu(struct mem_cgroup_stat_cpu);
-	if (!mem->stat)
+	memcg->stat = alloc_percpu(struct mem_cgroup_stat_cpu);
+	if (!memcg->stat)
 		goto out_free;
-	spin_lock_init(&mem->pcp_counter_lock);
-	return mem;
+	spin_lock_init(&memcg->pcp_counter_lock);
+	return memcg;
 
 out_free:
 	if (size < PAGE_SIZE)
-		kfree(mem);
+		kfree(memcg);
 	else
-		vfree(mem);
+		vfree(memcg);
 	return NULL;
 }
 
diff --git a/mm/memory.c b/mm/memory.c
index 5e30583..da645bd 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -878,15 +878,24 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
 			}
 			if (likely(!non_swap_entry(entry)))
 				rss[MM_SWAPENTS]++;
-			else if (is_write_migration_entry(entry) &&
-					is_cow_mapping(vm_flags)) {
-				/*
-				 * COW mappings require pages in both parent
-				 * and child to be set to read.
-				 */
-				make_migration_entry_read(&entry);
-				pte = swp_entry_to_pte(entry);
-				set_pte_at(src_mm, addr, src_pte, pte);
+			else if (is_migration_entry(entry)) {
+				page = migration_entry_to_page(entry);
+
+				if (PageAnon(page))
+					rss[MM_ANONPAGES]++;
+				else
+					rss[MM_FILEPAGES]++;
+
+				if (is_write_migration_entry(entry) &&
+				    is_cow_mapping(vm_flags)) {
+					/*
+					 * COW mappings require pages in both
+					 * parent and child to be set to read.
+					 */
+					make_migration_entry_read(&entry);
+					pte = swp_entry_to_pte(entry);
+					set_pte_at(src_mm, addr, src_pte, pte);
+				}
 			}
 		}
 		goto out_set_pte;
@@ -1191,6 +1200,16 @@ again:
 
 			if (!non_swap_entry(entry))
 				rss[MM_SWAPENTS]--;
+			else if (is_migration_entry(entry)) {
+				struct page *page;
+
+				page = migration_entry_to_page(entry);
+
+				if (PageAnon(page))
+					rss[MM_ANONPAGES]--;
+				else
+					rss[MM_FILEPAGES]--;
+			}
 			if (unlikely(!free_swap_and_cache(entry)))
 				print_bad_pte(vma, addr, ptent, NULL);
 		}
@@ -2428,7 +2447,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
 	 * fails, we just zero-fill it. Live with it.
 	 */
 	if (unlikely(!src)) {
-		void *kaddr = kmap_atomic(dst, KM_USER0);
+		void *kaddr = kmap_atomic(dst);
 		void __user *uaddr = (void __user *)(va & PAGE_MASK);
 
 		/*
@@ -2439,7 +2458,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
 		 */
 		if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
 			clear_page(kaddr);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		flush_dcache_page(dst);
 	} else
 		copy_user_highpage(dst, src, va, vma);
@@ -2861,6 +2880,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
 	struct mem_cgroup *ptr;
 	int exclusive = 0;
 	int ret = 0;
+	bool swap_token;
 
 	if (!pte_unmap_same(mm, pmd, page_table, orig_pte))
 		goto out;
@@ -2909,7 +2929,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		goto out_release;
 	}
 
+	swap_token = activate_swap_token(mm);
+
 	locked = lock_page_or_retry(page, mm, flags);
+
+	deactivate_swap_token(mm, swap_token);
+
 	delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
 	if (!locked) {
 		ret |= VM_FAULT_RETRY;
@@ -3156,6 +3181,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	struct vm_fault vmf;
 	int ret;
 	int page_mkwrite = 0;
+	bool swap_token;
 
 	/*
 	 * If we do COW later, allocate page befor taking lock_page()
@@ -3177,6 +3203,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	} else
 		cow_page = NULL;
 
+	swap_token = activate_swap_token(mm);
+
 	vmf.virtual_address = (void __user *)(address & PAGE_MASK);
 	vmf.pgoff = pgoff;
 	vmf.flags = flags;
@@ -3245,6 +3273,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
 	}
 
+	deactivate_swap_token(mm, swap_token);
+
 	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 
 	/*
@@ -3316,9 +3346,11 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 	return ret;
 
 unwritable_page:
+	deactivate_swap_token(mm, swap_token);
 	page_cache_release(page);
 	return ret;
 uncharge_out:
+	deactivate_swap_token(mm, swap_token);
 	/* fs's fault handler get error */
 	if (cow_page) {
 		mem_cgroup_uncharge_page(cow_page);
diff --git a/mm/migrate.c b/mm/migrate.c
index 9871a56..df141f6 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -445,7 +445,6 @@ void migrate_page_copy(struct page *newpage, struct page *page)
 	ClearPageSwapCache(page);
 	ClearPagePrivate(page);
 	set_page_private(page, 0);
-	page->mapping = NULL;
 
 	/*
 	 * If any waiters have accumulated on the new page then
@@ -667,6 +666,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
 	} else {
 		if (remap_swapcache)
 			remove_migration_ptes(page, newpage);
+		page->mapping = NULL;
 	}
 
 	unlock_page(newpage);
diff --git a/mm/mmap.c b/mm/mmap.c
index 3f758c7..f29c794 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -30,6 +30,7 @@
 #include <linux/perf_event.h>
 #include <linux/audit.h>
 #include <linux/khugepaged.h>
+#include <linux/uprobes.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -217,6 +218,7 @@ void unlink_file_vma(struct vm_area_struct *vma)
 		mutex_lock(&mapping->i_mmap_mutex);
 		__remove_shared_vm_struct(vma, file, mapping);
 		mutex_unlock(&mapping->i_mmap_mutex);
+		munmap_uprobe(vma);
 	}
 }
 
@@ -545,8 +547,14 @@ again:			remove_next = 1 + (end > next->vm_end);
 
 	if (file) {
 		mapping = file->f_mapping;
-		if (!(vma->vm_flags & VM_NONLINEAR))
+		if (!(vma->vm_flags & VM_NONLINEAR)) {
 			root = &mapping->i_mmap;
+			munmap_uprobe(vma);
+
+			if (adjust_next)
+				munmap_uprobe(next);
+		}
+
 		mutex_lock(&mapping->i_mmap_mutex);
 		if (insert) {
 			/*
@@ -616,8 +624,16 @@ again:			remove_next = 1 + (end > next->vm_end);
 	if (mapping)
 		mutex_unlock(&mapping->i_mmap_mutex);
 
+	if (root) {
+		mmap_uprobe(vma);
+
+		if (adjust_next)
+			mmap_uprobe(next);
+	}
+
 	if (remove_next) {
 		if (file) {
+			munmap_uprobe(next);
 			fput(file);
 			if (next->vm_flags & VM_EXECUTABLE)
 				removed_exe_file_vma(mm);
@@ -637,6 +653,8 @@ again:			remove_next = 1 + (end > next->vm_end);
 			goto again;
 		}
 	}
+	if (insert && file)
+		mmap_uprobe(insert);
 
 	validate_mm(mm);
 
@@ -1329,6 +1347,11 @@ out:
 			mm->locked_vm += (len >> PAGE_SHIFT);
 	} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
 		make_pages_present(addr, addr + len);
+
+	if (file && mmap_uprobe(vma))
+		/* matching probes but cannot insert */
+		goto unmap_and_free_vma;
+
 	return addr;
 
 unmap_and_free_vma:
@@ -2285,6 +2308,10 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
 	if ((vma->vm_flags & VM_ACCOUNT) &&
 	     security_vm_enough_memory_mm(mm, vma_pages(vma)))
 		return -ENOMEM;
+
+	if (vma->vm_file && mmap_uprobe(vma))
+		return -EINVAL;
+
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 	return 0;
 }
@@ -2354,6 +2381,10 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 			new_vma->vm_pgoff = pgoff;
 			if (new_vma->vm_file) {
 				get_file(new_vma->vm_file);
+
+				if (mmap_uprobe(new_vma))
+					goto out_free_mempol;
+
 				if (vma->vm_flags & VM_EXECUTABLE)
 					added_exe_file_vma(mm);
 			}
@@ -2477,6 +2508,11 @@ out:
 	return ret;
 }
 
+bool is_special_mapping(struct vm_area_struct *vma)
+{
+	return vma->vm_ops == &special_mapping_vmops;
+}
+
 static DEFINE_MUTEX(mm_all_locks_mutex);
 
 static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma)
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2958fd8..8561060 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -434,76 +434,29 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 }
 
 #define K(x) ((x) << (PAGE_SHIFT-10))
-static int oom_kill_task(struct task_struct *p)
-{
-	struct task_struct *q;
-	struct mm_struct *mm;
-
-	p = find_lock_task_mm(p);
-	if (!p)
-		return 1;
-
-	/* mm cannot be safely dereferenced after task_unlock(p) */
-	mm = p->mm;
-
-	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
-		task_pid_nr(p), p->comm, K(p->mm->total_vm),
-		K(get_mm_counter(p->mm, MM_ANONPAGES)),
-		K(get_mm_counter(p->mm, MM_FILEPAGES)));
-	task_unlock(p);
-
-	/*
-	 * Kill all user processes sharing p->mm in other thread groups, if any.
-	 * They don't get access to memory reserves or a higher scheduler
-	 * priority, though, to avoid depletion of all memory or task
-	 * starvation.  This prevents mm->mmap_sem livelock when an oom killed
-	 * task cannot exit because it requires the semaphore and its contended
-	 * by another thread trying to allocate memory itself.  That thread will
-	 * now get access to memory reserves since it has a pending fatal
-	 * signal.
-	 */
-	for_each_process(q)
-		if (q->mm == mm && !same_thread_group(q, p) &&
-		    !(q->flags & PF_KTHREAD)) {
-			if (q->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
-				continue;
-
-			task_lock(q);	/* Protect ->comm from prctl() */
-			pr_err("Kill process %d (%s) sharing same memory\n",
-				task_pid_nr(q), q->comm);
-			task_unlock(q);
-			force_sig(SIGKILL, q);
-		}
-
-	set_tsk_thread_flag(p, TIF_MEMDIE);
-	force_sig(SIGKILL, p);
-
-	return 0;
-}
-#undef K
-
-static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
-			    unsigned int points, unsigned long totalpages,
-			    struct mem_cgroup *memcg, nodemask_t *nodemask,
-			    const char *message)
+static void oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
+			     unsigned int points, unsigned long totalpages,
+			     struct mem_cgroup *memcg, nodemask_t *nodemask,
+			     const char *message)
 {
 	struct task_struct *victim = p;
 	struct task_struct *child;
 	struct task_struct *t = p;
+	struct mm_struct *mm;
 	unsigned int victim_points = 0;
 
-	if (printk_ratelimit())
-		dump_header(p, gfp_mask, order, memcg, nodemask);
-
 	/*
 	 * If the task is already exiting, don't alarm the sysadmin or kill
 	 * its children or threads, just set TIF_MEMDIE so it can die quickly
 	 */
 	if (p->flags & PF_EXITING) {
 		set_tsk_thread_flag(p, TIF_MEMDIE);
-		return 0;
+		return;
 	}
 
+	if (printk_ratelimit())
+		dump_header(p, gfp_mask, order, memcg, nodemask);
+
 	task_lock(p);
 	pr_err("%s: Kill process %d (%s) score %d or sacrifice child\n",
 		message, task_pid_nr(p), p->comm, points);
@@ -533,8 +486,44 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		}
 	} while_each_thread(p, t);
 
-	return oom_kill_task(victim);
+	victim = find_lock_task_mm(victim);
+	if (!victim)
+		return;
+
+	/* mm cannot safely be dereferenced after task_unlock(victim) */
+	mm = victim->mm;
+	pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
+		task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
+		K(get_mm_counter(victim->mm, MM_ANONPAGES)),
+		K(get_mm_counter(victim->mm, MM_FILEPAGES)));
+	task_unlock(victim);
+
+	/*
+	 * Kill all user processes sharing victim->mm in other thread groups, if
+	 * any.  They don't get access to memory reserves, though, to avoid
+	 * depletion of all memory.  This prevents mm->mmap_sem livelock when an
+	 * oom killed thread cannot exit because it requires the semaphore and
+	 * its contended by another thread trying to allocate memory itself.
+	 * That thread will now get access to memory reserves since it has a
+	 * pending fatal signal.
+	 */
+	for_each_process(p)
+		if (p->mm == mm && !same_thread_group(p, victim) &&
+		    !(p->flags & PF_KTHREAD)) {
+			if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+				continue;
+
+			task_lock(p);	/* Protect ->comm from prctl() */
+			pr_err("Kill process %d (%s) sharing same memory\n",
+				task_pid_nr(p), p->comm);
+			task_unlock(p);
+			force_sig(SIGKILL, p);
+		}
+
+	set_tsk_thread_flag(victim, TIF_MEMDIE);
+	force_sig(SIGKILL, victim);
 }
+#undef K
 
 /*
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.
@@ -580,15 +569,10 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask)
 	check_panic_on_oom(CONSTRAINT_MEMCG, gfp_mask, 0, NULL);
 	limit = mem_cgroup_get_limit(memcg) >> PAGE_SHIFT;
 	read_lock(&tasklist_lock);
-retry:
 	p = select_bad_process(&points, limit, memcg, NULL);
-	if (!p || PTR_ERR(p) == -1UL)
-		goto out;
-
-	if (oom_kill_process(p, gfp_mask, 0, points, limit, memcg, NULL,
-				"Memory cgroup out of memory"))
-		goto retry;
-out:
+	if (p && PTR_ERR(p) != -1UL)
+		oom_kill_process(p, gfp_mask, 0, points, limit, memcg, NULL,
+				 "Memory cgroup out of memory");
 	read_unlock(&tasklist_lock);
 }
 #endif
@@ -745,33 +729,24 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
 	if (sysctl_oom_kill_allocating_task &&
 	    !oom_unkillable_task(current, NULL, nodemask) &&
 	    current->mm) {
-		/*
-		 * oom_kill_process() needs tasklist_lock held.  If it returns
-		 * non-zero, current could not be killed so we must fallback to
-		 * the tasklist scan.
-		 */
-		if (!oom_kill_process(current, gfp_mask, order, 0, totalpages,
-				NULL, nodemask,
-				"Out of memory (oom_kill_allocating_task)"))
-			goto out;
+		oom_kill_process(current, gfp_mask, order, 0, totalpages, NULL,
+				 nodemask,
+				 "Out of memory (oom_kill_allocating_task)");
+		goto out;
 	}
 
-retry:
 	p = select_bad_process(&points, totalpages, NULL, mpol_mask);
-	if (PTR_ERR(p) == -1UL)
-		goto out;
-
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (!p) {
 		dump_header(NULL, gfp_mask, order, NULL, mpol_mask);
 		read_unlock(&tasklist_lock);
 		panic("Out of memory and no killable processes...\n");
 	}
-
-	if (oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
-				nodemask, "Out of memory"))
-		goto retry;
-	killed = 1;
+	if (PTR_ERR(p) != -1UL) {
+		oom_kill_process(p, gfp_mask, order, points, totalpages, NULL,
+				 nodemask, "Out of memory");
+		killed = 1;
+	}
 out:
 	read_unlock(&tasklist_lock);
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 0027d8f..6115633 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -191,8 +191,21 @@ static char * const zone_names[MAX_NR_ZONES] = {
 	 "Movable",
 };
 
+/*
+ * Try to keep at least this much lowmem free.  Do not allow normal
+ * allocations below this point, only high priority ones. Automatically
+ * tuned according to the amount of memory in the system.
+ */
 int min_free_kbytes = 1024;
 
+/*
+ * Extra memory for the system to try freeing between the min and
+ * low watermarks.  Useful for workloads that require low latency
+ * memory allocations in bursts larger than the normal gap between
+ * low and min.
+ */
+int extra_free_kbytes;
+
 static unsigned long __meminitdata nr_kernel_pages;
 static unsigned long __meminitdata nr_all_pages;
 static unsigned long __meminitdata dma_reserve;
@@ -4942,6 +4955,7 @@ static void setup_per_zone_lowmem_reserve(void)
 void setup_per_zone_wmarks(void)
 {
 	unsigned long pages_min = min_free_kbytes >> (PAGE_SHIFT - 10);
+	unsigned long pages_low = extra_free_kbytes >> (PAGE_SHIFT - 10);
 	unsigned long lowmem_pages = 0;
 	struct zone *zone;
 	unsigned long flags;
@@ -4953,11 +4967,14 @@ void setup_per_zone_wmarks(void)
 	}
 
 	for_each_zone(zone) {
-		u64 tmp;
+		u64 min, low;
 
 		spin_lock_irqsave(&zone->lock, flags);
-		tmp = (u64)pages_min * zone->present_pages;
-		do_div(tmp, lowmem_pages);
+		min = (u64)pages_min * zone->present_pages;
+		do_div(min, lowmem_pages);
+		low = (u64)pages_low * zone->present_pages;
+		do_div(low, vm_total_pages);
+
 		if (is_highmem(zone)) {
 			/*
 			 * __GFP_HIGH and PF_MEMALLOC allocations usually don't
@@ -4981,11 +4998,13 @@ void setup_per_zone_wmarks(void)
 			 * If it's a lowmem zone, reserve a number of pages
 			 * proportionate to the zone's size.
 			 */
-			zone->watermark[WMARK_MIN] = tmp;
+			zone->watermark[WMARK_MIN] = min;
 		}
 
-		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) + (tmp >> 2);
-		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) + (tmp >> 1);
+		zone->watermark[WMARK_LOW]  = min_wmark_pages(zone) +
+					low + (min >> 2);
+		zone->watermark[WMARK_HIGH] = min_wmark_pages(zone) +
+					low + (min >> 1);
 		setup_zone_migrate_reserve(zone);
 		spin_unlock_irqrestore(&zone->lock, flags);
 	}
@@ -5081,11 +5100,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 
+ * free_kbytes_sysctl_handler - just a wrapper around proc_dointvec() so
  *	that we can call two helper functions whenever min_free_kbytes
- *	changes.
+ *	or extra_free_kbytes changes.
  */
-int min_free_kbytes_sysctl_handler(ctl_table *table, int write, 
+int 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);
@@ -5236,6 +5255,7 @@ void *__init alloc_large_system_hash(const char *tablename,
 		max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
 		do_div(max, bucketsize);
 	}
+	max = min(max, 0x80000000ULL);
 
 	if (numentries > max)
 		numentries = max;
@@ -5413,7 +5433,25 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count)
 
 bool is_pageblock_removable_nolock(struct page *page)
 {
-	struct zone *zone = page_zone(page);
+	struct zone *zone;
+	unsigned long pfn;
+
+	/*
+	 * We have to be careful here because we are iterating over memory
+	 * sections which are not zone aware so we might end up outside of
+	 * the zone but still within the section.
+	 * We have to take care about the node as well. If the node is offline
+	 * its NODE_DATA will be NULL - see page_zone.
+	 */
+	if (!node_online(page_to_nid(page)))
+		return false;
+
+	zone = page_zone(page);
+	pfn = page_to_pfn(page);
+	if (zone->zone_start_pfn > pfn ||
+			zone->zone_start_pfn + zone->spanned_pages <= pfn)
+		return false;
+
 	return __count_immobile_pages(zone, page, 0);
 }
 
diff --git a/mm/rmap.c b/mm/rmap.c
index c8454e0..aa547d4 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -760,8 +760,7 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma,
 
 	/* Pretend the page is referenced if the task has the
 	   swap token and is in the middle of a page fault. */
-	if (mm != current->mm && has_swap_token(mm) &&
-			rwsem_is_locked(&mm->mmap_sem))
+	if (mm != current->mm && has_active_swap_token(mm))
 		referenced++;
 
 	(*mapcount)--;
diff --git a/mm/shmem.c b/mm/shmem.c
index feead19..b7e1955 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -379,7 +379,7 @@ static int shmem_free_swap(struct address_space *mapping,
 /*
  * Pagevec may contain swap entries, so shuffle up pages before releasing.
  */
-static void shmem_pagevec_release(struct pagevec *pvec)
+static void shmem_deswap_pagevec(struct pagevec *pvec)
 {
 	int i, j;
 
@@ -389,7 +389,36 @@ static void shmem_pagevec_release(struct pagevec *pvec)
 			pvec->pages[j++] = page;
 	}
 	pvec->nr = j;
-	pagevec_release(pvec);
+}
+
+/*
+ * SysV IPC SHM_UNLOCK restore Unevictable pages to their evictable lists.
+ */
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+	struct pagevec pvec;
+	pgoff_t indices[PAGEVEC_SIZE];
+	pgoff_t index = 0;
+
+	pagevec_init(&pvec, 0);
+	/*
+	 * Minor point, but we might as well stop if someone else SHM_LOCKs it.
+	 */
+	while (!mapping_unevictable(mapping)) {
+		/*
+		 * Avoid pagevec_lookup(): find_get_pages() returns 0 as if it
+		 * has finished, if it hits a row of PAGEVEC_SIZE swap entries.
+		 */
+		pvec.nr = shmem_find_get_pages_and_swap(mapping, index,
+					PAGEVEC_SIZE, pvec.pages, indices);
+		if (!pvec.nr)
+			break;
+		index = indices[pvec.nr - 1] + 1;
+		shmem_deswap_pagevec(&pvec);
+		check_move_unevictable_pages(pvec.pages, pvec.nr);
+		pagevec_release(&pvec);
+		cond_resched();
+	}
 }
 
 /*
@@ -440,7 +469,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 			}
 			unlock_page(page);
 		}
-		shmem_pagevec_release(&pvec);
+		shmem_deswap_pagevec(&pvec);
+		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 		cond_resched();
 		index++;
@@ -470,7 +500,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 			continue;
 		}
 		if (index == start && indices[0] > end) {
-			shmem_pagevec_release(&pvec);
+			shmem_deswap_pagevec(&pvec);
+			pagevec_release(&pvec);
 			break;
 		}
 		mem_cgroup_uncharge_start();
@@ -494,7 +525,8 @@ void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 			}
 			unlock_page(page);
 		}
-		shmem_pagevec_release(&pvec);
+		shmem_deswap_pagevec(&pvec);
+		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 		index++;
 	}
@@ -1068,13 +1100,6 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
 		user_shm_unlock(inode->i_size, user);
 		info->flags &= ~VM_LOCKED;
 		mapping_clear_unevictable(file->f_mapping);
-		/*
-		 * Ensure that a racing putback_lru_page() can see
-		 * the pages of this mapping are evictable when we
-		 * skip them due to !PageLRU during the scan.
-		 */
-		smp_mb__after_clear_bit();
-		scan_mapping_unevictable_pages(file->f_mapping);
 	}
 	retval = 0;
 
@@ -1631,9 +1656,9 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 		}
 		inode->i_mapping->a_ops = &shmem_aops;
 		inode->i_op = &shmem_symlink_inode_operations;
-		kaddr = kmap_atomic(page, KM_USER0);
+		kaddr = kmap_atomic(page);
 		memcpy(kaddr, symname, len);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 		set_page_dirty(page);
 		unlock_page(page);
 		page_cache_release(page);
@@ -2445,6 +2470,10 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
 	return 0;
 }
 
+void shmem_unlock_mapping(struct address_space *mapping)
+{
+}
+
 void shmem_truncate_range(struct inode *inode, loff_t lstart, loff_t lend)
 {
 	truncate_inode_pages_range(inode->i_mapping, lstart, lend);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index d999f09..00a962c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2427,9 +2427,9 @@ int add_swap_count_continuation(swp_entry_t entry, gfp_t gfp_mask)
 		if (!(count & COUNT_CONTINUED))
 			goto out;
 
-		map = kmap_atomic(list_page, KM_USER0) + offset;
+		map = kmap_atomic(list_page) + offset;
 		count = *map;
-		kunmap_atomic(map, KM_USER0);
+		kunmap_atomic(map);
 
 		/*
 		 * If this continuation count now has some space in it,
@@ -2472,7 +2472,7 @@ static bool swap_count_continued(struct swap_info_struct *si,
 
 	offset &= ~PAGE_MASK;
 	page = list_entry(head->lru.next, struct page, lru);
-	map = kmap_atomic(page, KM_USER0) + offset;
+	map = kmap_atomic(page) + offset;
 
 	if (count == SWAP_MAP_MAX)	/* initial increment from swap_map */
 		goto init_map;		/* jump over SWAP_CONT_MAX checks */
@@ -2482,26 +2482,26 @@ static bool swap_count_continued(struct swap_info_struct *si,
 		 * Think of how you add 1 to 999
 		 */
 		while (*map == (SWAP_CONT_MAX | COUNT_CONTINUED)) {
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 			page = list_entry(page->lru.next, struct page, lru);
 			BUG_ON(page == head);
-			map = kmap_atomic(page, KM_USER0) + offset;
+			map = kmap_atomic(page) + offset;
 		}
 		if (*map == SWAP_CONT_MAX) {
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 			page = list_entry(page->lru.next, struct page, lru);
 			if (page == head)
 				return false;	/* add count continuation */
-			map = kmap_atomic(page, KM_USER0) + offset;
+			map = kmap_atomic(page) + offset;
 init_map:		*map = 0;		/* we didn't zero the page */
 		}
 		*map += 1;
-		kunmap_atomic(map, KM_USER0);
+		kunmap_atomic(map);
 		page = list_entry(page->lru.prev, struct page, lru);
 		while (page != head) {
-			map = kmap_atomic(page, KM_USER0) + offset;
+			map = kmap_atomic(page) + offset;
 			*map = COUNT_CONTINUED;
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 			page = list_entry(page->lru.prev, struct page, lru);
 		}
 		return true;			/* incremented */
@@ -2512,22 +2512,22 @@ init_map:		*map = 0;		/* we didn't zero the page */
 		 */
 		BUG_ON(count != COUNT_CONTINUED);
 		while (*map == COUNT_CONTINUED) {
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 			page = list_entry(page->lru.next, struct page, lru);
 			BUG_ON(page == head);
-			map = kmap_atomic(page, KM_USER0) + offset;
+			map = kmap_atomic(page) + offset;
 		}
 		BUG_ON(*map == 0);
 		*map -= 1;
 		if (*map == 0)
 			count = 0;
-		kunmap_atomic(map, KM_USER0);
+		kunmap_atomic(map);
 		page = list_entry(page->lru.prev, struct page, lru);
 		while (page != head) {
-			map = kmap_atomic(page, KM_USER0) + offset;
+			map = kmap_atomic(page) + offset;
 			*map = SWAP_CONT_MAX | count;
 			count = COUNT_CONTINUED;
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 			page = list_entry(page->lru.prev, struct page, lru);
 		}
 		return count == COUNT_CONTINUED;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 86ce9a5..94dff88 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1906,9 +1906,9 @@ static int aligned_vread(char *buf, char *addr, unsigned long count)
 			 * we can expect USER0 is not used (see vread/vwrite's
 			 * function description)
 			 */
-			void *map = kmap_atomic(p, KM_USER0);
+			void *map = kmap_atomic(p);
 			memcpy(buf, map + offset, length);
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 		} else
 			memset(buf, 0, length);
 
@@ -1945,9 +1945,9 @@ static int aligned_vwrite(char *buf, char *addr, unsigned long count)
 			 * we can expect USER0 is not used (see vread/vwrite's
 			 * function description)
 			 */
-			void *map = kmap_atomic(p, KM_USER0);
+			void *map = kmap_atomic(p);
 			memcpy(map + offset, buf, length);
-			kunmap_atomic(map, KM_USER0);
+			kunmap_atomic(map);
 		}
 		addr += length;
 		buf += length;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2880396..61a6688 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -26,7 +26,6 @@
 #include <linux/buffer_head.h>	/* for try_to_release_page(),
 					buffer_heads_over_limit */
 #include <linux/mm_inline.h>
-#include <linux/pagevec.h>
 #include <linux/backing-dev.h>
 #include <linux/rmap.h>
 #include <linux/topology.h>
@@ -661,7 +660,7 @@ redo:
 		 * When racing with an mlock or AS_UNEVICTABLE clearing
 		 * (page is unlocked) make sure that if the other thread
 		 * does not observe our setting of PG_lru and fails
-		 * isolation/check_move_unevictable_page,
+		 * isolation/check_move_unevictable_pages,
 		 * we see PG_mlocked/AS_UNEVICTABLE cleared below and move
 		 * the page back to the evictable list.
 		 *
@@ -1510,7 +1509,7 @@ shrink_inactive_list(unsigned long nr_to_scan, struct mem_cgroup_zone *mz,
 	unsigned long nr_file;
 	unsigned long nr_dirty = 0;
 	unsigned long nr_writeback = 0;
-	isolate_mode_t reclaim_mode = ISOLATE_INACTIVE;
+	isolate_mode_t isolate_mode = ISOLATE_INACTIVE;
 	struct zone *zone = mz->zone;
 
 	while (unlikely(too_many_isolated(zone, file, sc))) {
@@ -1523,20 +1522,20 @@ shrink_inactive_list(unsigned long nr_to_scan, struct mem_cgroup_zone *mz,
 
 	set_reclaim_mode(priority, sc, false);
 	if (sc->reclaim_mode & RECLAIM_MODE_LUMPYRECLAIM)
-		reclaim_mode |= ISOLATE_ACTIVE;
+		isolate_mode |= ISOLATE_ACTIVE;
 
 	lru_add_drain();
 
 	if (!sc->may_unmap)
-		reclaim_mode |= ISOLATE_UNMAPPED;
+		isolate_mode |= ISOLATE_UNMAPPED;
 	if (!sc->may_writepage)
-		reclaim_mode |= ISOLATE_CLEAN;
+		isolate_mode |= ISOLATE_CLEAN;
 
 	spin_lock_irq(&zone->lru_lock);
 
 	nr_taken = isolate_lru_pages(nr_to_scan, mz, &page_list,
 				     &nr_scanned, sc->order,
-				     reclaim_mode, 0, file);
+				     isolate_mode, 0, file);
 	if (global_reclaim(sc)) {
 		zone->pages_scanned += nr_scanned;
 		if (current_is_kswapd())
@@ -1700,21 +1699,21 @@ static void shrink_active_list(unsigned long nr_to_scan,
 	struct page *page;
 	struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(mz);
 	unsigned long nr_rotated = 0;
-	isolate_mode_t reclaim_mode = ISOLATE_ACTIVE;
+	isolate_mode_t isolate_mode = ISOLATE_ACTIVE;
 	struct zone *zone = mz->zone;
 
 	lru_add_drain();
 
 	if (!sc->may_unmap)
-		reclaim_mode |= ISOLATE_UNMAPPED;
+		isolate_mode |= ISOLATE_UNMAPPED;
 	if (!sc->may_writepage)
-		reclaim_mode |= ISOLATE_CLEAN;
+		isolate_mode |= ISOLATE_CLEAN;
 
 	spin_lock_irq(&zone->lru_lock);
 
 	nr_taken = isolate_lru_pages(nr_to_scan, mz, &l_hold,
 				     &nr_scanned, sc->order,
-				     reclaim_mode, 1, file);
+				     isolate_mode, 1, file);
 	if (global_reclaim(sc))
 		zone->pages_scanned += nr_scanned;
 
@@ -3499,100 +3498,61 @@ int page_evictable(struct page *page, struct vm_area_struct *vma)
 	return 1;
 }
 
+#ifdef CONFIG_SHMEM
 /**
- * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
- * @page: page to check evictability and move to appropriate lru list
- * @zone: zone page is in
+ * check_move_unevictable_pages - check pages for evictability and move to appropriate zone lru list
+ * @pages:	array of pages to check
+ * @nr_pages:	number of pages to check
  *
- * Checks a page for evictability and moves the page to the appropriate
- * zone lru list.
+ * Checks pages for evictability and moves them to the appropriate lru list.
  *
- * Restrictions: zone->lru_lock must be held, page must be on LRU and must
- * have PageUnevictable set.
+ * This function is only used for SysV IPC SHM_UNLOCK.
  */
-static void check_move_unevictable_page(struct page *page, struct zone *zone)
+void check_move_unevictable_pages(struct page **pages, int nr_pages)
 {
 	struct lruvec *lruvec;
+	struct zone *zone = NULL;
+	int pgscanned = 0;
+	int pgrescued = 0;
+	int i;
 
-	VM_BUG_ON(PageActive(page));
-retry:
-	ClearPageUnevictable(page);
-	if (page_evictable(page, NULL)) {
-		enum lru_list l = page_lru_base_type(page);
-
-		__dec_zone_state(zone, NR_UNEVICTABLE);
-		lruvec = mem_cgroup_lru_move_lists(zone, page,
-						   LRU_UNEVICTABLE, l);
-		list_move(&page->lru, &lruvec->lists[l]);
-		__inc_zone_state(zone, NR_INACTIVE_ANON + l);
-		__count_vm_event(UNEVICTABLE_PGRESCUED);
-	} else {
-		/*
-		 * rotate unevictable list
-		 */
-		SetPageUnevictable(page);
-		lruvec = mem_cgroup_lru_move_lists(zone, page, LRU_UNEVICTABLE,
-						   LRU_UNEVICTABLE);
-		list_move(&page->lru, &lruvec->lists[LRU_UNEVICTABLE]);
-		if (page_evictable(page, NULL))
-			goto retry;
-	}
-}
-
-/**
- * scan_mapping_unevictable_pages - scan an address space for evictable pages
- * @mapping: struct address_space to scan for evictable pages
- *
- * Scan all pages in mapping.  Check unevictable pages for
- * evictability and move them to the appropriate zone lru list.
- */
-void scan_mapping_unevictable_pages(struct address_space *mapping)
-{
-	pgoff_t next = 0;
-	pgoff_t end   = (i_size_read(mapping->host) + PAGE_CACHE_SIZE - 1) >>
-			 PAGE_CACHE_SHIFT;
-	struct zone *zone;
-	struct pagevec pvec;
-
-	if (mapping->nrpages == 0)
-		return;
-
-	pagevec_init(&pvec, 0);
-	while (next < end &&
-		pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
-		int i;
-		int pg_scanned = 0;
-
-		zone = NULL;
-
-		for (i = 0; i < pagevec_count(&pvec); i++) {
-			struct page *page = pvec.pages[i];
-			pgoff_t page_index = page->index;
-			struct zone *pagezone = page_zone(page);
+	for (i = 0; i < nr_pages; i++) {
+		struct page *page = pages[i];
+		struct zone *pagezone;
 
-			pg_scanned++;
-			if (page_index > next)
-				next = page_index;
-			next++;
+		pgscanned++;
+		pagezone = page_zone(page);
+		if (pagezone != zone) {
+			if (zone)
+				spin_unlock_irq(&zone->lru_lock);
+			zone = pagezone;
+			spin_lock_irq(&zone->lru_lock);
+		}
 
-			if (pagezone != zone) {
-				if (zone)
-					spin_unlock_irq(&zone->lru_lock);
-				zone = pagezone;
-				spin_lock_irq(&zone->lru_lock);
-			}
+		if (!PageLRU(page) || !PageUnevictable(page))
+			continue;
 
-			if (PageLRU(page) && PageUnevictable(page))
-				check_move_unevictable_page(page, zone);
+		if (page_evictable(page, NULL)) {
+			enum lru_list lru = page_lru_base_type(page);
+
+			VM_BUG_ON(PageActive(page));
+			ClearPageUnevictable(page);
+			__dec_zone_state(zone, NR_UNEVICTABLE);
+			lruvec = mem_cgroup_lru_move_lists(zone, page,
+						LRU_UNEVICTABLE, lru);
+			list_move(&page->lru, &lruvec->lists[lru]);
+			__inc_zone_state(zone, NR_INACTIVE_ANON + lru);
+			pgrescued++;
 		}
-		if (zone)
-			spin_unlock_irq(&zone->lru_lock);
-		pagevec_release(&pvec);
-
-		count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned);
 	}
 
+	if (zone) {
+		__count_vm_events(UNEVICTABLE_PGRESCUED, pgrescued);
+		__count_vm_events(UNEVICTABLE_PGSCANNED, pgscanned);
+		spin_unlock_irq(&zone->lru_lock);
+	}
 }
+#endif /* CONFIG_SHMEM */
 
 static void warn_scan_unevictable_pages(void)
 {
diff --git a/net/core/kmap_skb.h b/net/core/kmap_skb.h
index 81e1ed7..52d0a44 100644
--- a/net/core/kmap_skb.h
+++ b/net/core/kmap_skb.h
@@ -7,12 +7,12 @@ static inline void *kmap_skb_frag(const skb_frag_t *frag)
 
 	local_bh_disable();
 #endif
-	return kmap_atomic(skb_frag_page(frag), KM_SKB_DATA_SOFTIRQ);
+	return kmap_atomic(skb_frag_page(frag));
 }
 
 static inline void kunmap_skb_frag(void *vaddr)
 {
-	kunmap_atomic(vaddr, KM_SKB_DATA_SOFTIRQ);
+	kunmap_atomic(vaddr);
 #ifdef CONFIG_HIGHMEM
 	local_bh_enable();
 #endif
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 9bcdec3..b1fbfc0 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3220,7 +3220,8 @@ void __init tcp_init(void)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long limit;
-	int i, max_share, cnt;
+	int max_share, cnt;
+	unsigned int i;
 	unsigned long jiffy = jiffies;
 
 	BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -3263,7 +3264,7 @@ void __init tcp_init(void)
 					&tcp_hashinfo.bhash_size,
 					NULL,
 					64 * 1024);
-	tcp_hashinfo.bhash_size = 1 << tcp_hashinfo.bhash_size;
+	tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size;
 	for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
 		spin_lock_init(&tcp_hashinfo.bhash[i].lock);
 		INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a225d5e..c02280a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -502,29 +502,31 @@ static void addrconf_forward_change(struct net *net, __s32 newf)
 	rcu_read_unlock();
 }
 
-static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old)
+static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
 {
 	struct net *net;
+	int old;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
 
 	net = (struct net *)table->extra2;
-	if (p == &net->ipv6.devconf_dflt->forwarding)
-		return 0;
+	old = *p;
+	*p = newf;
 
-	if (!rtnl_trylock()) {
-		/* Restore the original values before restarting */
-		*p = old;
-		return restart_syscall();
+	if (p == &net->ipv6.devconf_dflt->forwarding) {
+		rtnl_unlock();
+		return 0;
 	}
 
 	if (p == &net->ipv6.devconf_all->forwarding) {
-		__s32 newf = net->ipv6.devconf_all->forwarding;
 		net->ipv6.devconf_dflt->forwarding = newf;
 		addrconf_forward_change(net, newf);
-	} else if ((!*p) ^ (!old))
+	} else if ((!newf) ^ (!old))
 		dev_forward_change((struct inet6_dev *)table->extra1);
 	rtnl_unlock();
 
-	if (*p)
+	if (newf)
 		rt6_purge_dflt_routers(net);
 	return 1;
 }
@@ -4260,9 +4262,17 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write,
 	int *valp = ctl->data;
 	int val = *valp;
 	loff_t pos = *ppos;
+	ctl_table lctl;
 	int ret;
 
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	/*
+	 * ctl->data points to idev->cnf.forwarding, we should
+	 * not modify it until we get the rtnl lock.
+	 */
+	lctl = *ctl;
+	lctl.data = &val;
+
+	ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_fixup_forwarding(ctl, valp, val);
@@ -4300,26 +4310,27 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
 	rcu_read_unlock();
 }
 
-static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old)
+static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
 {
 	struct net *net;
+	int old;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
 
 	net = (struct net *)table->extra2;
+	old = *p;
+	*p = newf;
 
-	if (p == &net->ipv6.devconf_dflt->disable_ipv6)
+	if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
+		rtnl_unlock();
 		return 0;
-
-	if (!rtnl_trylock()) {
-		/* Restore the original values before restarting */
-		*p = old;
-		return restart_syscall();
 	}
 
 	if (p == &net->ipv6.devconf_all->disable_ipv6) {
-		__s32 newf = net->ipv6.devconf_all->disable_ipv6;
 		net->ipv6.devconf_dflt->disable_ipv6 = newf;
 		addrconf_disable_change(net, newf);
-	} else if ((!*p) ^ (!old))
+	} else if ((!newf) ^ (!old))
 		dev_disable_change((struct inet6_dev *)table->extra1);
 
 	rtnl_unlock();
@@ -4333,9 +4344,17 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write,
 	int *valp = ctl->data;
 	int val = *valp;
 	loff_t pos = *ppos;
+	ctl_table lctl;
 	int ret;
 
-	ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+	/*
+	 * ctl->data points to idev->cnf.disable_ipv6, we should
+	 * not modify it until we get the rtnl lock.
+	 */
+	lctl = *ctl;
+	lctl.data = &val;
+
+	ret = proc_dointvec(&lctl, write, buffer, lenp, ppos);
 
 	if (write)
 		ret = addrconf_disable_ipv6(ctl, valp, val);
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 38e6101..59edcd9 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -225,9 +225,9 @@ KEY_OPS(key);
 			    key, &key_##name##_ops);
 
 void ieee80211_debugfs_key_add(struct ieee80211_key *key)
-  {
+{
 	static int keycount;
-	char buf[50];
+	char buf[100];
 	struct sta_info *sta;
 
 	if (!key->local->debugfs.keys)
@@ -244,7 +244,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
 
 	sta = key->sta;
 	if (sta) {
-		sprintf(buf, "../../stations/%pM", sta->sta.addr);
+		sprintf(buf, "../../netdev:%s/stations/%pM",
+			sta->sdata->name, sta->sta.addr);
 		key->debugfs.stalink =
 			debugfs_create_symlink("station", key->debugfs.dir, buf);
 	}
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 73abb75..54df1b2 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -119,12 +119,12 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
 		      sizeof(mgmt->u.action.u.mesh_action);
 
-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+	skb = dev_alloc_skb(local->tx_headroom +
 			    hdr_len +
 			    2 + 37); /* max HWMP IE */
 	if (!skb)
 		return -1;
-	skb_reserve(skb, local->hw.extra_tx_headroom);
+	skb_reserve(skb, local->tx_headroom);
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
 	memset(mgmt, 0, hdr_len);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
@@ -250,12 +250,12 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 	if (time_before(jiffies, ifmsh->next_perr))
 		return -EAGAIN;
 
-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+	skb = dev_alloc_skb(local->tx_headroom +
 			    hdr_len +
 			    2 + 15 /* PERR IE */);
 	if (!skb)
 		return -1;
-	skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
+	skb_reserve(skb, local->tx_headroom);
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
 	memset(mgmt, 0, hdr_len);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 41ef1b4..a172517 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 	int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
 		      sizeof(mgmt->u.action.u.self_prot);
 
-	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+	skb = dev_alloc_skb(local->tx_headroom +
 			    hdr_len +
 			    2 + /* capability info */
 			    2 + /* AID */
@@ -186,7 +186,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 			    sdata->u.mesh.ie_len);
 	if (!skb)
 		return -1;
-	skb_reserve(skb, local->hw.extra_tx_headroom);
+	skb_reserve(skb, local->tx_headroom);
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
 	memset(mgmt, 0, hdr_len);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ecb4c84..295be92 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	struct ieee80211_work *wk;
 	u8 bssid[ETH_ALEN];
 	bool assoc_bss = false;
 
@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 		assoc_bss = true;
 	} else {
 		bool not_auth_yet = false;
+		struct ieee80211_work *tmp, *wk = NULL;
 
 		mutex_unlock(&ifmgd->mtx);
 
 		mutex_lock(&local->mtx);
-		list_for_each_entry(wk, &local->work_list, list) {
-			if (wk->sdata != sdata)
+		list_for_each_entry(tmp, &local->work_list, list) {
+			if (tmp->sdata != sdata)
 				continue;
 
-			if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
-			    wk->type != IEEE80211_WORK_AUTH &&
-			    wk->type != IEEE80211_WORK_ASSOC &&
-			    wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
+			if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
+			    tmp->type != IEEE80211_WORK_AUTH &&
+			    tmp->type != IEEE80211_WORK_ASSOC &&
+			    tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
 				continue;
 
-			if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
+			if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
 				continue;
 
-			not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
-			list_del_rcu(&wk->list);
-			free_work(wk);
+			not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
+			list_del_rcu(&tmp->list);
+			synchronize_rcu();
+			wk = tmp;
 			break;
 		}
 		mutex_unlock(&local->mtx);
 
+		if (wk && wk->type == IEEE80211_WORK_ASSOC) {
+			/* clean up dummy sta & TX sync */
+			sta_info_destroy_addr(wk->sdata, wk->filter_ta);
+			if (wk->assoc.synced)
+				drv_finish_tx_sync(local, wk->sdata,
+						   wk->filter_ta,
+						   IEEE80211_TX_SYNC_ASSOC);
+		} else if (wk && wk->type == IEEE80211_WORK_AUTH) {
+			if (wk->probe_auth.synced)
+				drv_finish_tx_sync(local, wk->sdata,
+						   wk->filter_ta,
+						   IEEE80211_TX_SYNC_AUTH);
+		}
+		kfree(wk);
+
 		/*
 		 * If somebody requests authentication and we haven't
 		 * sent out an auth frame yet there's no need to send
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 9307b03..0c62c76 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -584,6 +584,11 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 		return 0;
 
 	net = nf_ct_net(ct);
+
+	/* container deinit, netlink may have died before death_by_timeout */
+	if (!net->nfnl)
+		return 0;
+
 	if (!item->report && !nfnetlink_has_listeners(net, group))
 		return 0;
 
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 3aae66f..f81eba4 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -87,7 +87,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 	const struct xt_tee_tginfo *info = par->targinfo;
 	struct iphdr *iph;
 
-	if (percpu_read(tee_active))
+	if (__this_cpu_read(tee_active))
 		return XT_CONTINUE;
 	/*
 	 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for
@@ -124,9 +124,9 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
 	ip_send_check(iph);
 
 	if (tee_tg_route4(skb, info)) {
-		percpu_write(tee_active, true);
+		__this_cpu_write(tee_active, true);
 		ip_local_out(skb);
-		percpu_write(tee_active, false);
+		__this_cpu_write(tee_active, false);
 	} else {
 		kfree_skb(skb);
 	}
@@ -167,7 +167,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_tee_tginfo *info = par->targinfo;
 
-	if (percpu_read(tee_active))
+	if (__this_cpu_read(tee_active))
 		return XT_CONTINUE;
 	skb = pskb_copy(skb, GFP_ATOMIC);
 	if (skb == NULL)
@@ -185,9 +185,9 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
 		--iph->hop_limit;
 	}
 	if (tee_tg_route6(skb, info)) {
-		percpu_write(tee_active, true);
+		__this_cpu_write(tee_active, true);
 		ip6_local_out(skb);
-		percpu_write(tee_active, false);
+		__this_cpu_write(tee_active, false);
 	} else {
 		kfree_skb(skb);
 	}
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c
index e29e0ca..744a00d 100644
--- a/net/rds/ib_recv.c
+++ b/net/rds/ib_recv.c
@@ -763,7 +763,7 @@ static void rds_ib_cong_recv(struct rds_connection *conn,
 		to_copy = min(RDS_FRAG_SIZE - frag_off, PAGE_SIZE - map_off);
 		BUG_ON(to_copy & 7); /* Must be 64bit aligned. */
 
-		addr = kmap_atomic(sg_page(&frag->f_sg), KM_SOFTIRQ0);
+		addr = kmap_atomic(sg_page(&frag->f_sg));
 
 		src = addr + frag_off;
 		dst = (void *)map->m_page_addrs[map_page] + map_off;
@@ -773,7 +773,7 @@ static void rds_ib_cong_recv(struct rds_connection *conn,
 			uncongested |= ~(*src) & *dst;
 			*dst++ = *src++;
 		}
-		kunmap_atomic(addr, KM_SOFTIRQ0);
+		kunmap_atomic(addr);
 
 		copied += to_copy;
 
@@ -919,8 +919,7 @@ static void rds_ib_process_recv(struct rds_connection *conn,
 			rds_ib_cong_recv(conn, ibinc);
 		else {
 			rds_recv_incoming(conn, conn->c_faddr, conn->c_laddr,
-					  &ibinc->ii_inc, GFP_ATOMIC,
-					  KM_SOFTIRQ0);
+					  &ibinc->ii_inc, GFP_ATOMIC);
 			state->ack_next = be64_to_cpu(hdr->h_sequence);
 			state->ack_next_valid = 1;
 		}
diff --git a/net/rds/info.c b/net/rds/info.c
index f1c016c..9a6b4f6 100644
--- a/net/rds/info.c
+++ b/net/rds/info.c
@@ -104,7 +104,7 @@ EXPORT_SYMBOL_GPL(rds_info_deregister_func);
 void rds_info_iter_unmap(struct rds_info_iterator *iter)
 {
 	if (iter->addr) {
-		kunmap_atomic(iter->addr, KM_USER0);
+		kunmap_atomic(iter->addr);
 		iter->addr = NULL;
 	}
 }
@@ -119,7 +119,7 @@ void rds_info_copy(struct rds_info_iterator *iter, void *data,
 
 	while (bytes) {
 		if (!iter->addr)
-			iter->addr = kmap_atomic(*iter->pages, KM_USER0);
+			iter->addr = kmap_atomic(*iter->pages);
 
 		this = min(bytes, PAGE_SIZE - iter->offset);
 
@@ -134,7 +134,7 @@ void rds_info_copy(struct rds_info_iterator *iter, void *data,
 		iter->offset += this;
 
 		if (iter->offset == PAGE_SIZE) {
-			kunmap_atomic(iter->addr, KM_USER0);
+			kunmap_atomic(iter->addr);
 			iter->addr = NULL;
 			iter->offset = 0;
 			iter->pages++;
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c
index 5e57347..0bd9b5e 100644
--- a/net/rds/iw_recv.c
+++ b/net/rds/iw_recv.c
@@ -598,7 +598,7 @@ static void rds_iw_cong_recv(struct rds_connection *conn,
 		to_copy = min(RDS_FRAG_SIZE - frag_off, PAGE_SIZE - map_off);
 		BUG_ON(to_copy & 7); /* Must be 64bit aligned. */
 
-		addr = kmap_atomic(frag->f_page, KM_SOFTIRQ0);
+		addr = kmap_atomic(frag->f_page);
 
 		src = addr + frag_off;
 		dst = (void *)map->m_page_addrs[map_page] + map_off;
@@ -608,7 +608,7 @@ static void rds_iw_cong_recv(struct rds_connection *conn,
 			uncongested |= ~(*src) & *dst;
 			*dst++ = *src++;
 		}
-		kunmap_atomic(addr, KM_SOFTIRQ0);
+		kunmap_atomic(addr);
 
 		copied += to_copy;
 
@@ -754,8 +754,7 @@ static void rds_iw_process_recv(struct rds_connection *conn,
 			rds_iw_cong_recv(conn, iwinc);
 		else {
 			rds_recv_incoming(conn, conn->c_faddr, conn->c_laddr,
-					  &iwinc->ii_inc, GFP_ATOMIC,
-					  KM_SOFTIRQ0);
+					  &iwinc->ii_inc, GFP_ATOMIC);
 			state->ack_next = be64_to_cpu(hdr->h_sequence);
 			state->ack_next_valid = 1;
 		}
diff --git a/net/rds/loop.c b/net/rds/loop.c
index bca6761..87ff2a8 100644
--- a/net/rds/loop.c
+++ b/net/rds/loop.c
@@ -79,7 +79,7 @@ static int rds_loop_xmit(struct rds_connection *conn, struct rds_message *rm,
 	rds_message_addref(rm);
 
 	rds_recv_incoming(conn, conn->c_laddr, conn->c_faddr, &rm->m_inc,
-			  GFP_KERNEL, KM_USER0);
+			  GFP_KERNEL);
 
 	rds_send_drop_acked(conn, be64_to_cpu(rm->m_inc.i_hdr.h_sequence),
 			    NULL);
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 7eaba18..ec1d731 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -704,7 +704,7 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
 		  __be32 saddr);
 void rds_inc_put(struct rds_incoming *inc);
 void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
-		       struct rds_incoming *inc, gfp_t gfp, enum km_type km);
+		       struct rds_incoming *inc, gfp_t gfp);
 int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
 		size_t size, int msg_flags);
 void rds_clear_recv_queue(struct rds_sock *rs);
diff --git a/net/rds/recv.c b/net/rds/recv.c
index bc3f8cd..5c6e9f1 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -155,7 +155,7 @@ static void rds_recv_incoming_exthdrs(struct rds_incoming *inc, struct rds_sock
  * tell us which roles the addrs in the conn are playing for this message.
  */
 void rds_recv_incoming(struct rds_connection *conn, __be32 saddr, __be32 daddr,
-		       struct rds_incoming *inc, gfp_t gfp, enum km_type km)
+		       struct rds_incoming *inc, gfp_t gfp)
 {
 	struct rds_sock *rs = NULL;
 	struct sock *sk;
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
index 78205e2..6243258 100644
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -169,7 +169,6 @@ static void rds_tcp_cong_recv(struct rds_connection *conn,
 struct rds_tcp_desc_arg {
 	struct rds_connection *conn;
 	gfp_t gfp;
-	enum km_type km;
 };
 
 static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
@@ -255,7 +254,7 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
 			else
 				rds_recv_incoming(conn, conn->c_faddr,
 						  conn->c_laddr, &tinc->ti_inc,
-						  arg->gfp, arg->km);
+						  arg->gfp);
 
 			tc->t_tinc_hdr_rem = sizeof(struct rds_header);
 			tc->t_tinc_data_rem = 0;
@@ -272,8 +271,7 @@ out:
 }
 
 /* the caller has to hold the sock lock */
-static int rds_tcp_read_sock(struct rds_connection *conn, gfp_t gfp,
-			     enum km_type km)
+static int rds_tcp_read_sock(struct rds_connection *conn, gfp_t gfp)
 {
 	struct rds_tcp_connection *tc = conn->c_transport_data;
 	struct socket *sock = tc->t_sock;
@@ -283,7 +281,6 @@ static int rds_tcp_read_sock(struct rds_connection *conn, gfp_t gfp,
 	/* It's like glib in the kernel! */
 	arg.conn = conn;
 	arg.gfp = gfp;
-	arg.km = km;
 	desc.arg.data = &arg;
 	desc.error = 0;
 	desc.count = 1; /* give more than one skb per call */
@@ -311,7 +308,7 @@ int rds_tcp_recv(struct rds_connection *conn)
 	rdsdebug("recv worker conn %p tc %p sock %p\n", conn, tc, sock);
 
 	lock_sock(sock->sk);
-	ret = rds_tcp_read_sock(conn, GFP_KERNEL, KM_USER0);
+	ret = rds_tcp_read_sock(conn, GFP_KERNEL);
 	release_sock(sock->sk);
 
 	return ret;
@@ -336,7 +333,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes)
 	ready = tc->t_orig_data_ready;
 	rds_tcp_stats_inc(s_tcp_data_ready_calls);
 
-	if (rds_tcp_read_sock(conn, GFP_ATOMIC, KM_SOFTIRQ0) == -ENOMEM)
+	if (rds_tcp_read_sock(conn, GFP_ATOMIC) == -ENOMEM)
 		queue_delayed_work(rds_wq, &conn->c_recv_w, 0);
 out:
 	read_unlock_bh(&sk->sk_callback_lock);
diff --git a/net/socket.c b/net/socket.c
index 28a96af..784d93a 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -479,7 +479,7 @@ static struct socket *sock_alloc(void)
 	inode->i_uid = current_fsuid();
 	inode->i_gid = current_fsgid();
 
-	percpu_add(sockets_in_use, 1);
+	this_cpu_add(sockets_in_use, 1);
 	return sock;
 }
 
@@ -522,7 +522,7 @@ void sock_release(struct socket *sock)
 	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
 
-	percpu_sub(sockets_in_use, 1);
+	this_cpu_sub(sockets_in_use, 1);
 	if (!sock->file) {
 		iput(SOCK_INODE(sock));
 		return;
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 2763e3e..38f388c 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -82,9 +82,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize)
 					>>PAGE_CACHE_SHIFT;
 		unsigned int offset = (buf->page_base + len - 1)
 					& (PAGE_CACHE_SIZE - 1);
-		ptr = kmap_atomic(buf->pages[last], KM_USER0);
+		ptr = kmap_atomic(buf->pages[last]);
 		pad = *(ptr + offset);
-		kunmap_atomic(ptr, KM_USER0);
+		kunmap_atomic(ptr);
 		goto out;
 	} else
 		len -= buf->page_len;
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
index 145e6784..0a648c5 100644
--- a/net/sunrpc/socklib.c
+++ b/net/sunrpc/socklib.c
@@ -114,7 +114,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct
 		}
 
 		len = PAGE_CACHE_SIZE;
-		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
+		kaddr = kmap_atomic(*ppage);
 		if (base) {
 			len -= base;
 			if (pglen < len)
@@ -127,7 +127,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct
 			ret = copy_actor(desc, kaddr, len);
 		}
 		flush_dcache_page(*ppage);
-		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+		kunmap_atomic(kaddr);
 		copied += ret;
 		if (ret != len || !desc->count)
 			goto out;
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 593f4c6..b97a3dd 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -122,9 +122,9 @@ xdr_terminate_string(struct xdr_buf *buf, const u32 len)
 {
 	char *kaddr;
 
-	kaddr = kmap_atomic(buf->pages[0], KM_USER0);
+	kaddr = kmap_atomic(buf->pages[0]);
 	kaddr[buf->page_base + len] = '\0';
-	kunmap_atomic(kaddr, KM_USER0);
+	kunmap_atomic(kaddr);
 }
 EXPORT_SYMBOL_GPL(xdr_terminate_string);
 
@@ -232,12 +232,12 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base,
 		pgto_base -= copy;
 		pgfrom_base -= copy;
 
-		vto = kmap_atomic(*pgto, KM_USER0);
-		vfrom = kmap_atomic(*pgfrom, KM_USER1);
+		vto = kmap_atomic(*pgto);
+		vfrom = kmap_atomic(*pgfrom);
 		memmove(vto + pgto_base, vfrom + pgfrom_base, copy);
 		flush_dcache_page(*pgto);
-		kunmap_atomic(vfrom, KM_USER1);
-		kunmap_atomic(vto, KM_USER0);
+		kunmap_atomic(vfrom);
+		kunmap_atomic(vto);
 
 	} while ((len -= copy) != 0);
 }
@@ -267,9 +267,9 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len)
 		if (copy > len)
 			copy = len;
 
-		vto = kmap_atomic(*pgto, KM_USER0);
+		vto = kmap_atomic(*pgto);
 		memcpy(vto + pgbase, p, copy);
-		kunmap_atomic(vto, KM_USER0);
+		kunmap_atomic(vto);
 
 		len -= copy;
 		if (len == 0)
@@ -311,9 +311,9 @@ _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len)
 		if (copy > len)
 			copy = len;
 
-		vfrom = kmap_atomic(*pgfrom, KM_USER0);
+		vfrom = kmap_atomic(*pgfrom);
 		memcpy(p, vfrom + pgbase, copy);
-		kunmap_atomic(vfrom, KM_USER0);
+		kunmap_atomic(vfrom);
 
 		pgbase += copy;
 		if (pgbase == PAGE_CACHE_SIZE) {
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 554d081..1776e57 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -338,9 +338,9 @@ rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad)
 			curlen = copy_len;
 		dprintk("RPC:       %s: page %d destp 0x%p len %d curlen %d\n",
 			__func__, i, destp, copy_len, curlen);
-		srcp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA);
+		srcp = kmap_atomic(ppages[i]);
 		memcpy(destp, srcp+page_base, curlen);
-		kunmap_atomic(srcp, KM_SKB_SUNRPC_DATA);
+		kunmap_atomic(srcp);
 		rqst->rq_svec[0].iov_len += curlen;
 		destp += curlen;
 		copy_len -= curlen;
@@ -639,10 +639,10 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
 			dprintk("RPC:       %s: page %d"
 				" srcp 0x%p len %d curlen %d\n",
 				__func__, i, srcp, copy_len, curlen);
-			destp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA);
+			destp = kmap_atomic(ppages[i]);
 			memcpy(destp + page_base, srcp, curlen);
 			flush_dcache_page(ppages[i]);
-			kunmap_atomic(destp, KM_SKB_SUNRPC_DATA);
+			kunmap_atomic(destp);
 			srcp += curlen;
 			copy_len -= curlen;
 			if (copy_len == 0)
diff --git a/samples/Kconfig b/samples/Kconfig
index 41063e7..7b6792a 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -61,4 +61,12 @@ config SAMPLE_KDB
 	  Build an example of how to dynamically add the hello
 	  command to the kdb shell.
 
+config SAMPLE_RPMSG_CLIENT
+	tristate "Build rpmsg client sample -- loadable modules only"
+	depends on RPMSG && m
+	help
+	  Build an rpmsg client sample driver, which demonstrates how
+	  to communicate with an AMP-configured remote processor over
+	  the rpmsg bus.
+
 endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 6280817..2f75851 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,4 +1,4 @@
 # Makefile for Linux samples code
 
 obj-$(CONFIG_SAMPLES)	+= kobject/ kprobes/ tracepoints/ trace_events/ \
-			   hw_breakpoint/ kfifo/ kdb/ hidraw/
+			   hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/
diff --git a/samples/rpmsg/Makefile b/samples/rpmsg/Makefile
new file mode 100644
index 0000000..2d4973c
--- /dev/null
+++ b/samples/rpmsg/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SAMPLE_RPMSG_CLIENT) += rpmsg_client_sample.o
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
new file mode 100644
index 0000000..23ea9f2
--- /dev/null
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -0,0 +1,100 @@
+/*
+ * Remote processor messaging - sample client driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+
+#define MSG		"hello world!"
+#define MSG_LIMIT	100
+
+static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
+						void *priv, u32 src)
+{
+	int ret;
+	static int rx_count;
+
+	dev_info(&rpdev->dev, "incoming msg %d (src: 0x%x)\n", ++rx_count, src);
+
+	print_hex_dump(KERN_DEBUG, __func__, DUMP_PREFIX_NONE, 16, 1,
+		       data, len,  true);
+
+	/* samples should not live forever */
+	if (rx_count >= MSG_LIMIT) {
+		dev_info(&rpdev->dev, "goodbye!\n");
+		return;
+	}
+
+	/* send a new message now */
+	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	if (ret)
+		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+}
+
+static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
+{
+	int ret;
+
+	dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
+					rpdev->src, rpdev->dst);
+
+	/* send a message to our remote processor */
+	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	if (ret) {
+		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __devexit rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+{
+	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
+}
+
+static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
+	{ .name	= "rpmsg-client-sample" },
+	{ },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
+
+static struct rpmsg_driver rpmsg_sample_client = {
+	.drv.name	= KBUILD_MODNAME,
+	.drv.owner	= THIS_MODULE,
+	.id_table	= rpmsg_driver_sample_id_table,
+	.probe		= rpmsg_sample_probe,
+	.callback	= rpmsg_sample_cb,
+	.remove		= __devexit_p(rpmsg_sample_remove),
+};
+
+static int __init rpmsg_client_sample_init(void)
+{
+	return register_rpmsg_driver(&rpmsg_sample_client);
+}
+module_init(rpmsg_client_sample_init);
+
+static void __exit rpmsg_client_sample_fini(void)
+{
+	unregister_rpmsg_driver(&rpmsg_sample_client);
+}
+module_exit(rpmsg_client_sample_fini);
+
+MODULE_DESCRIPTION("Remote processor messaging sample client driver");
+MODULE_LICENSE("GPL v2");
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 7966265..dce29cd 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -3,7 +3,7 @@
 # These targets are used from top-level makefile
 
 PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \
-	localmodconfig localyesconfig
+	localmodconfig localyesconfig kvmconfig
 
 ifdef KBUILD_KCONFIG
 Kconfig := $(KBUILD_KCONFIG)
@@ -33,6 +33,11 @@ silentoldconfig: $(obj)/conf
 	$(Q)mkdir -p include/generated
 	$< --$@ $(Kconfig)
 
+kvmconfig:
+	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/config -e KVMTOOL_TEST_ENABLE
+	$(Q)yes "" | make oldconfig > /dev/null
+	@echo 'Kernel configuration modified to run as KVM guest.'
+
 localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
 	$(Q)mkdir -p include/generated
 	$(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config
diff --git a/security/keys/internal.h b/security/keys/internal.h
index c7a7cae..65647f8 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -33,6 +33,7 @@
 
 extern struct key_type key_type_dead;
 extern struct key_type key_type_user;
+extern struct key_type key_type_logon;
 
 /*****************************************************************************/
 /*
diff --git a/security/keys/key.c b/security/keys/key.c
index 4f64c72..7ada801 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -999,6 +999,7 @@ void __init key_init(void)
 	list_add_tail(&key_type_keyring.link, &key_types_list);
 	list_add_tail(&key_type_dead.link, &key_types_list);
 	list_add_tail(&key_type_user.link, &key_types_list);
+	list_add_tail(&key_type_logon.link, &key_types_list);
 
 	/* record the root user tracking */
 	rb_link_node(&root_key_user.node,
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 2aee3c5..c7660a2 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -18,6 +18,8 @@
 #include <asm/uaccess.h>
 #include "internal.h"
 
+static int logon_vet_description(const char *desc);
+
 /*
  * user defined keys take an arbitrary string as the description and an
  * arbitrary blob of data as the payload
@@ -36,6 +38,24 @@ struct key_type key_type_user = {
 EXPORT_SYMBOL_GPL(key_type_user);
 
 /*
+ * This key type is essentially the same as key_type_user, but it does
+ * not define a .read op. This is suitable for storing username and
+ * password pairs in the keyring that you do not want to be readable
+ * from userspace.
+ */
+struct key_type key_type_logon = {
+	.name			= "logon",
+	.instantiate		= user_instantiate,
+	.update			= user_update,
+	.match			= user_match,
+	.revoke			= user_revoke,
+	.destroy		= user_destroy,
+	.describe		= user_describe,
+	.vet_description	= logon_vet_description,
+};
+EXPORT_SYMBOL_GPL(key_type_logon);
+
+/*
  * instantiate a user defined key
  */
 int user_instantiate(struct key *key, const void *data, size_t datalen)
@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
 }
 
 EXPORT_SYMBOL_GPL(user_read);
+
+/* Vet the description for a "logon" key */
+static int logon_vet_description(const char *desc)
+{
+	char *p;
+
+	/* require a "qualified" description string */
+	p = strchr(desc, ':');
+	if (!p)
+		return -EINVAL;
+
+	/* also reject description with ':' as first char */
+	if (p == desc)
+		return -EINVAL;
+
+	return 0;
+}
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 9027ac1..3865145 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -886,12 +886,12 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
 		 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
 		 * So do I.
 		 */
-		char *kaddr = kmap_atomic(page, KM_USER0);
+		char *kaddr = kmap_atomic(page);
 
 		dump->page = page;
 		memcpy(dump->data + offset, kaddr + offset,
 		       PAGE_SIZE - offset);
-		kunmap_atomic(kaddr, KM_USER0);
+		kunmap_atomic(kaddr);
 	}
 	/* Same with put_arg_page(page) in fs/exec.c */
 #ifdef CONFIG_MMU
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c
index 5b68435..501501e 100644
--- a/sound/pci/hda/alc880_quirks.c
+++ b/sound/pci/hda/alc880_quirks.c
@@ -762,16 +762,22 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
 	/* Looks like the unsol event is incompatible with the standard
 	 * definition.  4bit tag is placed at 28 bit!
 	 */
-	switch (res >> 28) {
+	res >>= 28;
+	switch (res) {
 	case ALC_MIC_EVENT:
 		alc88x_simple_mic_automute(codec);
 		break;
 	default:
-		alc_sku_unsol_event(codec, res);
+		alc_exec_unsol_event(codec, res);
 		break;
 	}
 }
 
+static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	alc_exec_unsol_event(codec, res >> 28);
+}
+
 static void alc880_uniwill_p53_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -800,10 +806,11 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
 	/* Looks like the unsol event is incompatible with the standard
 	 * definition.  4bit tag is placed at 28 bit!
 	 */
-	if ((res >> 28) == ALC_DCVOL_EVENT)
+	res >>= 28;
+	if (res == ALC_DCVOL_EVENT)
 		alc880_uniwill_p53_dcvol_automute(codec);
 	else
-		alc_sku_unsol_event(codec, res);
+		alc_exec_unsol_event(codec, res);
 }
 
 /*
@@ -1677,7 +1684,7 @@ static const struct alc_config_preset alc880_presets[] = {
 		.channel_mode = alc880_lg_ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc880_lg_capture_source,
-		.unsol_event = alc_sku_unsol_event,
+		.unsol_event = alc880_unsol_event,
 		.setup = alc880_lg_setup,
 		.init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c
index bdf0ed4..bb364a5 100644
--- a/sound/pci/hda/alc882_quirks.c
+++ b/sound/pci/hda/alc882_quirks.c
@@ -730,6 +730,11 @@ static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
 		alc889A_mb31_automute(codec);
 }
 
+static void alc882_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	alc_exec_unsol_event(codec, res >> 26);
+}
+
 /*
  * configuration and preset
  */
@@ -775,7 +780,7 @@ static const struct alc_config_preset alc882_presets[] = {
 			.channel_mode = alc885_mba21_ch_modes,
 			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
 			.input_mux = &alc882_capture_source,
-			.unsol_event = alc_sku_unsol_event,
+			.unsol_event = alc882_unsol_event,
 			.setup = alc885_mba21_setup,
 			.init_hook = alc_hp_automute,
        },
@@ -791,7 +796,7 @@ static const struct alc_config_preset alc882_presets[] = {
 		.input_mux = &alc882_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
+		.unsol_event = alc882_unsol_event,
 		.setup = alc885_mbp3_setup,
 		.init_hook = alc_hp_automute,
 	},
@@ -806,7 +811,7 @@ static const struct alc_config_preset alc882_presets[] = {
 		.input_mux = &mb5_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
+		.unsol_event = alc882_unsol_event,
 		.setup = alc885_mb5_setup,
 		.init_hook = alc_hp_automute,
 	},
@@ -821,7 +826,7 @@ static const struct alc_config_preset alc882_presets[] = {
 		.input_mux = &macmini3_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
+		.unsol_event = alc882_unsol_event,
 		.setup = alc885_macmini3_setup,
 		.init_hook = alc_hp_automute,
 	},
@@ -836,7 +841,7 @@ static const struct alc_config_preset alc882_presets[] = {
 		.input_mux = &alc889A_imac91_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_sku_unsol_event,
+		.unsol_event = alc882_unsol_event,
 		.setup = alc885_imac91_setup,
 		.init_hook = alc_hp_automute,
 	},
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 5e82acf..ddbed97 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -185,7 +185,6 @@ struct alc_spec {
 	unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
 	unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
 	unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
-	unsigned int use_jack_tbl:1; /* 1 for model=auto */
 
 	/* auto-mute control */
 	int automute_mode;
@@ -621,17 +620,10 @@ static void alc_mic_automute(struct hda_codec *codec)
 		alc_mux_select(codec, 0, spec->int_mic_idx, false);
 }
 
-/* unsolicited event for HP jack sensing */
-static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+/* handle the specified unsol action (ALC_XXX_EVENT) */
+static void alc_exec_unsol_event(struct hda_codec *codec, int action)
 {
-	struct alc_spec *spec = codec->spec;
-	if (codec->vendor_id == 0x10ec0880)
-		res >>= 28;
-	else
-		res >>= 26;
-	if (spec->use_jack_tbl)
-		res = snd_hda_jack_get_action(codec, res);
-	switch (res) {
+	switch (action) {
 	case ALC_HP_EVENT:
 		alc_hp_automute(codec);
 		break;
@@ -645,6 +637,18 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 	snd_hda_jack_report_sync(codec);
 }
 
+/* unsolicited event for HP jack sensing */
+static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+	struct alc_spec *spec = codec->spec;
+	if (codec->vendor_id == 0x10ec0880)
+		res >>= 28;
+	else
+		res >>= 26;
+	res = snd_hda_jack_get_action(codec, res);
+	alc_exec_unsol_event(codec, res);
+}
+
 /* call init functions of standard auto-mute helpers */
 static void alc_inithook(struct hda_codec *codec)
 {
@@ -1883,7 +1887,7 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = {
 };
 #endif
 
-static int alc_build_controls(struct hda_codec *codec)
+static int __alc_build_controls(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	struct snd_kcontrol *kctl = NULL;
@@ -2029,11 +2033,16 @@ static int alc_build_controls(struct hda_codec *codec)
 
 	alc_free_kctls(codec); /* no longer needed */
 
-	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+	return 0;
+}
+
+static int alc_build_controls(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int err = __alc_build_controls(codec);
 	if (err < 0)
 		return err;
-
-	return 0;
+	return snd_hda_jack_add_kctls(codec, &spec->autocfg);
 }
 
 
@@ -3233,7 +3242,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
 	int i, err, noutputs;
 
 	noutputs = cfg->line_outs;
-	if (spec->multi_ios > 0)
+	if (spec->multi_ios > 0 && cfg->line_outs < 3)
 		noutputs += spec->multi_ios;
 
 	for (i = 0; i < noutputs; i++) {
@@ -3904,7 +3913,6 @@ static void set_capture_mixer(struct hda_codec *codec)
 static void alc_auto_init_std(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	spec->use_jack_tbl = 1;
 	alc_auto_init_multi_out(codec);
 	alc_auto_init_extra_out(codec);
 	alc_auto_init_analog_input(codec);
@@ -4168,6 +4176,8 @@ static int patch_alc880(struct hda_codec *codec)
 	codec->patch_ops = alc_patch_ops;
 	if (board_config == ALC_MODEL_AUTO)
 		spec->init_hook = alc_auto_init_std;
+	else
+		codec->patch_ops.build_controls = __alc_build_controls;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (!spec->loopback.amplist)
 		spec->loopback.amplist = alc880_loopbacks;
@@ -4297,6 +4307,8 @@ static int patch_alc260(struct hda_codec *codec)
 	codec->patch_ops = alc_patch_ops;
 	if (board_config == ALC_MODEL_AUTO)
 		spec->init_hook = alc_auto_init_std;
+	else
+		codec->patch_ops.build_controls = __alc_build_controls;
 	spec->shutup = alc_eapd_shutup;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (!spec->loopback.amplist)
@@ -4691,6 +4703,8 @@ static int patch_alc882(struct hda_codec *codec)
 	codec->patch_ops = alc_patch_ops;
 	if (board_config == ALC_MODEL_AUTO)
 		spec->init_hook = alc_auto_init_std;
+	else
+		codec->patch_ops.build_controls = __alc_build_controls;
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	if (!spec->loopback.amplist)
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index f8863eb..7f4ba81 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -987,12 +987,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
 	/* restore regular registers */
 	for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
 
-		/* this regs depends on the others */
+		/* These regs should restore in particular order */
 		if (reg == SGTL5000_CHIP_ANA_POWER ||
 			reg == SGTL5000_CHIP_CLK_CTRL ||
 			reg == SGTL5000_CHIP_LINREG_CTRL ||
 			reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
-			reg == SGTL5000_CHIP_CLK_CTRL)
+			reg == SGTL5000_CHIP_REF_CTRL)
 			continue;
 
 		snd_soc_write(codec, reg, cache[reg]);
@@ -1003,8 +1003,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
 		snd_soc_write(codec, reg, cache[reg]);
 
 	/*
-	 * restore power and other regs according
-	 * to set_power() and set_clock()
+	 * restore these regs according to the power setting sequence in
+	 * sgtl5000_set_power_regs() and clock setting sequence in
+	 * sgtl5000_set_clock().
+	 *
+	 * The order of restore is:
+	 * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+	 *    SGTL5000_CHIP_ANA_POWER PLL bits set
+	 * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+	 *    SGTL5000_CHIP_ANA_POWER LINREG_D restored
+	 * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+	 *    prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
 	 */
 	snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
 			cache[SGTL5000_CHIP_LINREG_CTRL]);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index eb401ef..372b0b8 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -60,7 +60,6 @@ struct aic32x4_rate_divs {
 
 struct aic32x4_priv {
 	u32 sysclk;
-	s32 master;
 	u8 page_no;
 	void *control_data;
 	u32 power_cfg;
@@ -369,7 +368,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
 	struct snd_soc_codec *codec = codec_dai->codec;
-	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
 	u8 iface_reg_1;
 	u8 iface_reg_2;
 	u8 iface_reg_3;
@@ -384,11 +382,9 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 	/* set master/slave audio interface */
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
-		aic32x4->master = 1;
 		iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFS:
-		aic32x4->master = 0;
 		break;
 	default:
 		printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
@@ -526,64 +522,58 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
 static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
 				  enum snd_soc_bias_level level)
 {
-	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-
 	switch (level) {
 	case SND_SOC_BIAS_ON:
-		if (aic32x4->master) {
-			/* Switch on PLL */
-			snd_soc_update_bits(codec, AIC32X4_PLLPR,
-					    AIC32X4_PLLEN, AIC32X4_PLLEN);
-
-			/* Switch on NDAC Divider */
-			snd_soc_update_bits(codec, AIC32X4_NDAC,
-					    AIC32X4_NDACEN, AIC32X4_NDACEN);
-
-			/* Switch on MDAC Divider */
-			snd_soc_update_bits(codec, AIC32X4_MDAC,
-					    AIC32X4_MDACEN, AIC32X4_MDACEN);
-
-			/* Switch on NADC Divider */
-			snd_soc_update_bits(codec, AIC32X4_NADC,
-					    AIC32X4_NADCEN, AIC32X4_NADCEN);
-
-			/* Switch on MADC Divider */
-			snd_soc_update_bits(codec, AIC32X4_MADC,
-					    AIC32X4_MADCEN, AIC32X4_MADCEN);
-
-			/* Switch on BCLK_N Divider */
-			snd_soc_update_bits(codec, AIC32X4_BCLKN,
-					    AIC32X4_BCLKEN, AIC32X4_BCLKEN);
-		}
+		/* Switch on PLL */
+		snd_soc_update_bits(codec, AIC32X4_PLLPR,
+				    AIC32X4_PLLEN, AIC32X4_PLLEN);
+
+		/* Switch on NDAC Divider */
+		snd_soc_update_bits(codec, AIC32X4_NDAC,
+				    AIC32X4_NDACEN, AIC32X4_NDACEN);
+
+		/* Switch on MDAC Divider */
+		snd_soc_update_bits(codec, AIC32X4_MDAC,
+				    AIC32X4_MDACEN, AIC32X4_MDACEN);
+
+		/* Switch on NADC Divider */
+		snd_soc_update_bits(codec, AIC32X4_NADC,
+				    AIC32X4_NADCEN, AIC32X4_NADCEN);
+
+		/* Switch on MADC Divider */
+		snd_soc_update_bits(codec, AIC32X4_MADC,
+				    AIC32X4_MADCEN, AIC32X4_MADCEN);
+
+		/* Switch on BCLK_N Divider */
+		snd_soc_update_bits(codec, AIC32X4_BCLKN,
+				    AIC32X4_BCLKEN, AIC32X4_BCLKEN);
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
 	case SND_SOC_BIAS_STANDBY:
-		if (aic32x4->master) {
-			/* Switch off PLL */
-			snd_soc_update_bits(codec, AIC32X4_PLLPR,
-					    AIC32X4_PLLEN, 0);
-
-			/* Switch off NDAC Divider */
-			snd_soc_update_bits(codec, AIC32X4_NDAC,
-					    AIC32X4_NDACEN, 0);
-
-			/* Switch off MDAC Divider */
-			snd_soc_update_bits(codec, AIC32X4_MDAC,
-					    AIC32X4_MDACEN, 0);
-
-			/* Switch off NADC Divider */
-			snd_soc_update_bits(codec, AIC32X4_NADC,
-					    AIC32X4_NADCEN, 0);
-
-			/* Switch off MADC Divider */
-			snd_soc_update_bits(codec, AIC32X4_MADC,
-					    AIC32X4_MADCEN, 0);
-
-			/* Switch off BCLK_N Divider */
-			snd_soc_update_bits(codec, AIC32X4_BCLKN,
-					    AIC32X4_BCLKEN, 0);
-		}
+		/* Switch off PLL */
+		snd_soc_update_bits(codec, AIC32X4_PLLPR,
+				    AIC32X4_PLLEN, 0);
+
+		/* Switch off NDAC Divider */
+		snd_soc_update_bits(codec, AIC32X4_NDAC,
+				    AIC32X4_NDACEN, 0);
+
+		/* Switch off MDAC Divider */
+		snd_soc_update_bits(codec, AIC32X4_MDAC,
+				    AIC32X4_MDACEN, 0);
+
+		/* Switch off NADC Divider */
+		snd_soc_update_bits(codec, AIC32X4_NADC,
+				    AIC32X4_NADCEN, 0);
+
+		/* Switch off MADC Divider */
+		snd_soc_update_bits(codec, AIC32X4_MADC,
+				    AIC32X4_MADCEN, 0);
+
+		/* Switch off BCLK_N Divider */
+		snd_soc_update_bits(codec, AIC32X4_BCLKN,
+				    AIC32X4_BCLKEN, 0);
 		break;
 	case SND_SOC_BIAS_OFF:
 		break;
@@ -651,9 +641,11 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
 		snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
 	}
-	if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
-		snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
-	}
+
+	tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
+			AIC32X4_LDOCTLEN : 0;
+	snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
+
 	tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
 	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
 		tmp_reg |= AIC32X4_LDOIN_18_36;
diff --git a/tools/kvm/.gitignore b/tools/kvm/.gitignore
new file mode 100644
index 0000000..be6c6f2
--- /dev/null
+++ b/tools/kvm/.gitignore
@@ -0,0 +1,11 @@
+/lkvm
+/vm
+*.o
+*.d
+.cscope
+tags
+include/common-cmds.h
+tests/boot/boot_test.iso
+tests/boot/rootfs/
+guest/init
+KVMTOOLS-VERSION-FILE
diff --git a/tools/kvm/CREDITS-Git b/tools/kvm/CREDITS-Git
new file mode 100644
index 0000000..c2ddcb3
--- /dev/null
+++ b/tools/kvm/CREDITS-Git
@@ -0,0 +1,30 @@
+Most of the infrastructure that 'perf' uses here has been reused
+from the Git project, as of version:
+
+    66996ec: Sync with 1.6.2.4
+
+Here is an (incomplete!) list of main contributors to those files
+in util/* and elsewhere:
+
+ Alex Riesen
+ Christian Couder
+ Dmitry Potapov
+ Jeff King
+ Johannes Schindelin
+ Johannes Sixt
+ Junio C Hamano
+ Linus Torvalds
+ Matthias Kestenholz
+ Michal Ostrowski
+ Miklos Vajna
+ Petr Baudis
+ Pierre Habouzit
+ René Scharfe
+ Samuel Tardieu
+ Shawn O. Pearce
+ Steffen Prohaska
+ Steve Haslam
+
+Thanks guys!
+
+The full history of the files can be found in the upstream Git commits.
diff --git a/tools/kvm/Documentation/kernel-debugging.txt b/tools/kvm/Documentation/kernel-debugging.txt
new file mode 100644
index 0000000..98b9438
--- /dev/null
+++ b/tools/kvm/Documentation/kernel-debugging.txt
@@ -0,0 +1,15 @@
+This document explains how to debug a guests' kernel using KGDB.
+
+1. Run the guest:
+        'lkvm run -k [vmlinuz] -p "kgdboc=ttyS1 kgdbwait" --tty 1'
+
+And see which PTY got assigned to ttyS1 (you'll see:
+'  Info: Assigned terminal 1 to pty /dev/pts/X').
+
+2. Run GDB on the host:
+        'gdb [vmlinuz]'
+
+3. Connect to the guest (from within GDB):
+        'target remote /dev/pty/X'
+
+4. Start debugging! (enter 'continue' to continue boot).
diff --git a/tools/kvm/Documentation/kvm-balloon.txt b/tools/kvm/Documentation/kvm-balloon.txt
new file mode 100644
index 0000000..efc0a87
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-balloon.txt
@@ -0,0 +1,24 @@
+lkvm-balloon(1)
+================
+
+NAME
+----
+lkvm-balloon - Inflate or deflate the virtio balloon
+
+SYNOPSIS
+--------
+[verse]
+'lkvm balloon [command] [size] [instance]'
+
+DESCRIPTION
+-----------
+The command inflates or deflates the virtio balloon located in the
+specified instance.
+For a list of running instances see 'lkvm list'.
+
+Command can be either 'inflate' or 'deflate'. Inflate increases the
+size of the balloon, thus decreasing the amount of virtual RAM available
+for the guest. Deflation returns previously inflated memory back to the
+guest.
+
+size is specified in Mb.
diff --git a/tools/kvm/Documentation/kvm-debug.txt b/tools/kvm/Documentation/kvm-debug.txt
new file mode 100644
index 0000000..a8eb2c0
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-debug.txt
@@ -0,0 +1,16 @@
+lkvm-debug(1)
+================
+
+NAME
+----
+lkvm-debug - Print debug information from a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm debug [instance]'
+
+DESCRIPTION
+-----------
+The command prints debug information from a running instance.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-list.txt b/tools/kvm/Documentation/kvm-list.txt
new file mode 100644
index 0000000..a245607
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-list.txt
@@ -0,0 +1,16 @@
+lkvm-list(1)
+================
+
+NAME
+----
+lkvm-list - Print a list of running instances on the host.
+
+SYNOPSIS
+--------
+[verse]
+'lkvm list'
+
+DESCRIPTION
+-----------
+This command prints a list of running instances on the host which
+belong to the user who currently ran 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-pause.txt b/tools/kvm/Documentation/kvm-pause.txt
new file mode 100644
index 0000000..1ea2a23
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-pause.txt
@@ -0,0 +1,16 @@
+lkvm-pause(1)
+================
+
+NAME
+----
+lkvm-pause - Pause the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm pause [instance]'
+
+DESCRIPTION
+-----------
+The command pauses a virtual machine.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-resume.txt b/tools/kvm/Documentation/kvm-resume.txt
new file mode 100644
index 0000000..a36c4df
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-resume.txt
@@ -0,0 +1,16 @@
+lkvm-resume(1)
+================
+
+NAME
+----
+lkvm-resume - Resume the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm resume [instance]'
+
+DESCRIPTION
+-----------
+The command resumes a virtual machine.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-run.txt b/tools/kvm/Documentation/kvm-run.txt
new file mode 100644
index 0000000..8ddf470
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-run.txt
@@ -0,0 +1,62 @@
+lkvm-run(1)
+================
+
+NAME
+----
+lkvm-run - Start the virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm run' [-k <kernel image> | --kernel <kernel image>]
+
+DESCRIPTION
+-----------
+The command starts a virtual machine.
+
+OPTIONS
+-------
+-m::
+--mem=::
+	Virtual machine memory size in MiB.
+
+-p::
+--params::
+	Additional kernel command line arguments.
+
+-r::
+--initrd=::
+	Initial RAM disk image.
+
+-k::
+--kernel=::
+	The virtual machine kernel.
+
+--dev=::
+	KVM device file.
+
+-i::
+--image=::
+	A disk image file.
+
+-s::
+--single-step::
+	Enable single stepping.
+
+-g::
+--ioport-debug::
+	Enable ioport debugging.
+
+-c::
+--enable-virtio-console::
+	Enable the virtual IO console.
+
+--cpus::
+	The number of virtual CPUs to run.
+
+--debug::
+	Enable debug messages.
+
+SEE ALSO
+--------
+linkkvm:
diff --git a/tools/kvm/Documentation/kvm-sandbox.txt b/tools/kvm/Documentation/kvm-sandbox.txt
new file mode 100644
index 0000000..2d7f558
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-sandbox.txt
@@ -0,0 +1,16 @@
+lkvm-sandbox(1)
+================
+
+NAME
+----
+lkvm-sandbox - Run a command in a sandboxed guest
+
+SYNOPSIS
+--------
+[verse]
+'lkvm sandbox ['lkvm run' arguments] -- [sandboxed command]'
+
+DESCRIPTION
+-----------
+The sandboxed command will run in a guest as part of it's init
+command.
diff --git a/tools/kvm/Documentation/kvm-setup.txt b/tools/kvm/Documentation/kvm-setup.txt
new file mode 100644
index 0000000..4b6e331
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-setup.txt
@@ -0,0 +1,15 @@
+lkvm-setup(1)
+================
+
+NAME
+----
+lkvm-setup - Setup a new virtual machine
+
+SYNOPSIS
+--------
+[verse]
+'lkvm setup <name>'
+
+DESCRIPTION
+-----------
+The command setups a virtual machine.
diff --git a/tools/kvm/Documentation/kvm-stat.txt b/tools/kvm/Documentation/kvm-stat.txt
new file mode 100644
index 0000000..101ce7a
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-stat.txt
@@ -0,0 +1,19 @@
+lkvm-stat(1)
+================
+
+NAME
+----
+lkvm-stat - Print statistics about a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm [command] [-n instance] [-p instance pid] [--all]'
+
+DESCRIPTION
+-----------
+The command prints statistics about a running instance.
+For a list of running instances see 'lkvm list'.
+
+Commands:
+ --memory, -m	Display memory statistics
diff --git a/tools/kvm/Documentation/kvm-stop.txt b/tools/kvm/Documentation/kvm-stop.txt
new file mode 100644
index 0000000..6e4bc83
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-stop.txt
@@ -0,0 +1,16 @@
+lkvm-stop(1)
+================
+
+NAME
+----
+lkvm-stop - Stop a running instance
+
+SYNOPSIS
+--------
+[verse]
+'lkvm stop [instance]'
+
+DESCRIPTION
+-----------
+The command stops a running instance.
+For a list of running instances see 'lkvm list'.
diff --git a/tools/kvm/Documentation/kvm-version.txt b/tools/kvm/Documentation/kvm-version.txt
new file mode 100644
index 0000000..41003d2
--- /dev/null
+++ b/tools/kvm/Documentation/kvm-version.txt
@@ -0,0 +1,21 @@
+lkvm-version(1)
+================
+
+NAME
+----
+lkvm-version - Print the version of the kernel tree kvm tools
+was built on.
+
+SYNOPSIS
+--------
+[verse]
+'lkvm version'
+
+DESCRIPTION
+-----------
+The command prints the version of the kernel that was used to build
+kvm tools.
+
+Note that the version is not the version of the kernel which is currently
+running on the host, but is the version of the kernel tree from which kvm
+tools was built.
diff --git a/tools/kvm/Documentation/virtio-console.txt b/tools/kvm/Documentation/virtio-console.txt
new file mode 100644
index 0000000..4a58d56
--- /dev/null
+++ b/tools/kvm/Documentation/virtio-console.txt
@@ -0,0 +1,41 @@
+General
+--------
+
+virtio-console as the name implies is a console over virtio transport. Here is
+a simple head to head comparison of the virtio-console vs regular 8250 console:
+
+8250 serial console:
+
+ - Requires CONFIG_SERIAL_8250=y and CONFIG_SERIAL_8250_CONSOLE=y kernel configs,
+which are enabled almost everywhere.
+ - Doesn't require guest-side changes.
+ - Compatible with older guests.
+
+virtio-console:
+
+ - Requires CONFIG_VIRTIO_CONSOLE=y (along with all other virtio dependencies),
+which got enabled only in recent kernels (but not all of them).
+ - Much faster.
+ - Consumes less processing resources.
+ - Requires guest-side changes.
+
+Enabling virtio-console
+------------------------
+
+First, make sure guest kernel is built with CONFIG_VIRTIO_CONSOLE=y. Once this
+is done, the following has to be done inside guest image:
+
+ - Add the following line to /etc/inittab:
+	'hvc0:2345:respawn:/sbin/agetty -L 9600 hvc0'
+ - Add 'hvc0' to /etc/securetty (so you could actually log on)
+ - Start the guest with '--console virtio'
+
+Common errors
+--------------
+
+Q: I don't see anything on the screen!
+A: Make sure CONFIG_VIRTIO_CONSOLE=y is enabled in the *guest* kernel, also
+make sure you've updated /etc/inittab
+
+Q: It won't accept my username/password, but I enter them correctly!
+A: You didn't add 'hvc0' to /etc/securetty
diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
new file mode 100644
index 0000000..1aef516
--- /dev/null
+++ b/tools/kvm/Makefile
@@ -0,0 +1,364 @@
+#
+# Define WERROR=0 to disable -Werror.
+#
+
+ifeq ($(strip $(V)),)
+	E = @echo
+	Q = @
+else
+	E = @\#
+	Q =
+endif
+ifneq ($(I), )
+	KINCL_PATH=$(I)
+else
+	KINCL_PATH=../..
+endif
+export E Q KINCL_PATH
+
+include config/utilities.mak
+include config/feature-tests.mak
+
+FIND	:= find
+CSCOPE	:= cscope
+TAGS	:= ctags
+
+PROGRAM	:= lkvm
+PROGRAM_ALIAS := vm
+
+GUEST_INIT := guest/init
+GUEST_INIT_S2 := guest/init_stage2
+
+OBJS	+= builtin-balloon.o
+OBJS	+= builtin-debug.o
+OBJS	+= builtin-help.o
+OBJS	+= builtin-list.o
+OBJS	+= builtin-stat.o
+OBJS	+= builtin-pause.o
+OBJS	+= builtin-resume.o
+OBJS	+= builtin-run.o
+OBJS	+= builtin-setup.o
+OBJS	+= builtin-stop.o
+OBJS	+= builtin-version.o
+OBJS	+= disk/core.o
+OBJS	+= framebuffer.o
+OBJS	+= guest_compat.o
+OBJS	+= hw/rtc.o
+OBJS	+= hw/serial.o
+OBJS	+= ioport.o
+OBJS	+= kvm-cpu.o
+OBJS	+= kvm.o
+OBJS	+= main.o
+OBJS	+= mmio.o
+OBJS	+= pci.o
+OBJS	+= term.o
+OBJS	+= virtio/blk.o
+OBJS	+= virtio/console.o
+OBJS	+= virtio/core.o
+OBJS	+= virtio/net.o
+OBJS	+= virtio/rng.o
+OBJS    += virtio/balloon.o
+OBJS	+= virtio/pci.o
+OBJS	+= virtio/trans.o
+OBJS	+= disk/blk.o
+OBJS	+= disk/qcow.o
+OBJS	+= disk/raw.o
+OBJS	+= ioeventfd.o
+OBJS	+= net/uip/core.o
+OBJS	+= net/uip/arp.o
+OBJS	+= net/uip/icmp.o
+OBJS	+= net/uip/ipv4.o
+OBJS	+= net/uip/tcp.o
+OBJS	+= net/uip/udp.o
+OBJS	+= net/uip/buf.o
+OBJS	+= net/uip/csum.o
+OBJS	+= net/uip/dhcp.o
+OBJS	+= kvm-cmd.o
+OBJS	+= util/rbtree.o
+OBJS	+= util/threadpool.o
+OBJS	+= util/parse-options.o
+OBJS	+= util/rbtree-interval.o
+OBJS	+= util/strbuf.o
+OBJS	+= util/read-write.o
+OBJS	+= util/util.o
+OBJS	+= virtio/9p.o
+OBJS	+= virtio/9p-pdu.o
+OBJS	+= hw/vesa.o
+OBJS	+= hw/pci-shmem.o
+OBJS	+= kvm-ipc.o
+OBJS	+= builtin-sandbox.o
+
+# Additional ARCH settings for x86
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
+                  -e s/arm.*/arm/ -e s/sa110/arm/ \
+                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
+                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
+                  -e s/sh[234].*/sh/ )
+
+uname_M      := $(shell uname -m | sed -e s/i.86/i386/)
+ifeq ($(uname_M),i386)
+	ARCH         := x86
+	DEFINES      += -DCONFIG_X86_32
+endif
+ifeq ($(uname_M),x86_64)
+	ARCH         := x86
+	DEFINES      += -DCONFIG_X86_64
+endif
+
+
+### Arch-specific stuff
+
+#x86
+ifeq ($(ARCH),x86)
+	DEFINES += -DCONFIG_X86
+	OBJS	+= x86/cpuid.o
+	OBJS	+= x86/interrupt.o
+	OBJS	+= x86/ioport.o
+	OBJS	+= x86/irq.o
+	OBJS	+= x86/kvm.o
+	OBJS	+= x86/kvm-cpu.o
+	OBJS	+= x86/mptable.o
+	OBJS	+= hw/i8042.o
+# Exclude BIOS object files from header dependencies.
+	OTHEROBJS	+= x86/bios.o
+	OTHEROBJS	+= x86/bios/bios-rom.o
+	ARCH_INCLUDE := x86/include
+endif
+# POWER/ppc:  Actually only support ppc64 currently.
+ifeq ($(uname_M), ppc64)
+	DEFINES += -DCONFIG_PPC
+	OBJS	+= powerpc/ioport.o
+	OBJS	+= powerpc/irq.o
+	OBJS	+= powerpc/kvm.o
+	OBJS	+= powerpc/kvm-cpu.o
+	ARCH_INCLUDE := powerpc/include
+	CFLAGS += -m64
+endif
+
+###
+
+ifeq (,$(ARCH_INCLUDE))
+	UNSUPP_ERR = @echo "This architecture is not supported in kvmtool." && exit 1
+else
+	UNSUPP_ERR =
+endif
+
+
+FLAGS_BFD := $(CFLAGS) -lbfd
+has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD))
+ifeq ($(has_bfd),y)
+	CFLAGS	+= -DCONFIG_HAS_BFD
+	OBJS	+= symbol.o
+	LIBS	+= -lbfd
+endif
+
+FLAGS_VNCSERVER := $(CFLAGS) -lvncserver
+has_vncserver := $(call try-cc,$(SOURCE_VNCSERVER),$(FLAGS_VNCSERVER))
+ifeq ($(has_vncserver),y)
+	OBJS	+= ui/vnc.o
+	CFLAGS	+= -DCONFIG_HAS_VNCSERVER
+	LIBS	+= -lvncserver
+endif
+
+FLAGS_SDL := $(CFLAGS) -lSDL
+has_SDL := $(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL))
+ifeq ($(has_SDL),y)
+	OBJS	+= ui/sdl.o
+	CFLAGS	+= -DCONFIG_HAS_SDL
+	LIBS	+= -lSDL
+endif
+
+FLAGS_ZLIB := $(CFLAGS) -lz
+has_ZLIB := $(call try-cc,$(SOURCE_ZLIB),$(FLAGS_ZLIB))
+ifeq ($(has_ZLIB),y)
+	CFLAGS	+= -DCONFIG_HAS_ZLIB
+	LIBS	+= -lz
+endif
+
+FLAGS_AIO := $(CFLAGS) -laio
+has_AIO := $(call try-cc,$(SOURCE_AIO),$(FLAGS_AIO))
+ifeq ($(has_AIO),y)
+	CFLAGS	+= -DCONFIG_HAS_AIO
+	LIBS	+= -laio
+endif
+
+LIBS	+= -lrt
+LIBS	+= -lpthread
+LIBS	+= -lutil
+
+
+DEPS	:= $(patsubst %.o,%.d,$(OBJS))
+OBJS	+= $(OTHEROBJS)
+
+DEFINES	+= -D_FILE_OFFSET_BITS=64
+DEFINES	+= -D_GNU_SOURCE
+DEFINES	+= -DKVMTOOLS_VERSION='"$(KVMTOOLS_VERSION)"'
+DEFINES	+= -DBUILD_ARCH='"$(ARCH)"'
+
+KVM_INCLUDE := include
+CFLAGS	+= $(CPPFLAGS) $(DEFINES) -I$(KVM_INCLUDE) -I$(ARCH_INCLUDE) -I$(KINCL_PATH)/include -I$(KINCL_PATH)/arch/$(ARCH)/include/ -Os -g
+
+ifneq ($(WERROR),0)
+	WARNINGS += -Werror
+endif
+
+WARNINGS += -Wall
+WARNINGS += -Wcast-align
+WARNINGS += -Wformat=2
+WARNINGS += -Winit-self
+WARNINGS += -Wmissing-declarations
+WARNINGS += -Wmissing-prototypes
+WARNINGS += -Wnested-externs
+WARNINGS += -Wno-system-headers
+WARNINGS += -Wold-style-definition
+WARNINGS += -Wredundant-decls
+WARNINGS += -Wsign-compare
+WARNINGS += -Wstrict-prototypes
+WARNINGS += -Wundef
+WARNINGS += -Wvolatile-register-var
+WARNINGS += -Wwrite-strings
+
+CFLAGS	+= $(WARNINGS)
+
+all: arch_support_check $(PROGRAM) $(PROGRAM_ALIAS) $(GUEST_INIT) $(GUEST_INIT_S2)
+
+arch_support_check:
+	$(UNSUPP_ERR)
+
+KVMTOOLS-VERSION-FILE:
+	@$(SHELL_PATH) util/KVMTOOLS-VERSION-GEN $(OUTPUT)
+-include $(OUTPUT)KVMTOOLS-VERSION-FILE
+
+$(PROGRAM): $(DEPS) $(OBJS)
+	$(E) "  LINK    " $@
+	$(Q) $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $@
+
+$(PROGRAM_ALIAS): $(PROGRAM)
+	$(E) "  LN      " $@
+	$(Q) ln -f $(PROGRAM) $@
+
+$(GUEST_INIT): guest/init.c
+	$(E) "  LINK    " $@
+	$(Q) $(CC) -static guest/init.c -o $@
+
+$(GUEST_INIT_S2): guest/init_stage2.c
+	$(E) "  LINK    " $@
+	$(Q) $(CC) -static guest/init_stage2.c -o $@
+
+$(DEPS):
+
+util/rbtree.d: ../../lib/rbtree.c
+	$(Q) $(CC) -M -MT util/rbtree.o $(CFLAGS) $< -o $@
+
+%.d: %.c
+	$(Q) $(CC) -M -MT $(patsubst %.d,%.o,$@) $(CFLAGS) $< -o $@
+
+# The header file common-cmds.h is needed for compilation of builtin-help.c.
+builtin-help.d: $(KVM_INCLUDE)/common-cmds.h
+
+$(OBJS):
+
+util/rbtree.o: ../../lib/rbtree.c
+	$(E) "  CC      " $@
+	$(Q) $(CC) -c $(CFLAGS) $< -o $@
+
+%.o: %.c
+	$(E) "  CC      " $@
+	$(Q) $(CC) -c $(CFLAGS) $< -o $@
+
+
+$(KVM_INCLUDE)/common-cmds.h: util/generate-cmdlist.sh command-list.txt
+
+$(KVM_INCLUDE)/common-cmds.h: $(wildcard Documentation/kvm-*.txt)
+	$(E) "  GEN     " $@
+	$(Q) util/generate-cmdlist.sh > $@+ && mv $@+ $@
+
+#
+# BIOS assembly weirdness
+#
+BIOS_CFLAGS += -m32
+BIOS_CFLAGS += -march=i386
+BIOS_CFLAGS += -mregparm=3
+
+BIOS_CFLAGS += -fno-stack-protector
+BIOS_CFLAGS += -I../../arch/$(ARCH)
+
+x86/bios.o: x86/bios/bios.bin x86/bios/bios-rom.h
+
+x86/bios/bios.bin.elf: x86/bios/entry.S x86/bios/e820.c x86/bios/int10.c x86/bios/int15.c x86/bios/rom.ld.S
+	$(E) "  CC       x86/bios/memcpy.o"
+	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/memcpy.c -o x86/bios/memcpy.o
+	$(E) "  CC       x86/bios/e820.o"
+	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/e820.c -o x86/bios/e820.o
+	$(E) "  CC       x86/bios/int10.o"
+	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int10.c -o x86/bios/int10.o
+	$(E) "  CC       x86/bios/int15.o"
+	$(Q) $(CC) -include code16gcc.h $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/int15.c -o x86/bios/int15.o
+	$(E) "  CC       x86/bios/entry.o"
+	$(Q) $(CC) $(CFLAGS) $(BIOS_CFLAGS) -c -s x86/bios/entry.S -o x86/bios/entry.o
+	$(E) "  LD      " $@
+	$(Q) ld -T x86/bios/rom.ld.S -o x86/bios/bios.bin.elf x86/bios/memcpy.o x86/bios/entry.o x86/bios/e820.o x86/bios/int10.o x86/bios/int15.o
+
+x86/bios/bios.bin: x86/bios/bios.bin.elf
+	$(E) "  OBJCOPY " $@
+	$(Q) objcopy -O binary -j .text x86/bios/bios.bin.elf x86/bios/bios.bin
+
+x86/bios/bios-rom.o: x86/bios/bios-rom.S x86/bios/bios.bin x86/bios/bios-rom.h
+	$(E) "  CC      " $@
+	$(Q) $(CC) -c $(CFLAGS) x86/bios/bios-rom.S -o x86/bios/bios-rom.o
+
+x86/bios/bios-rom.h: x86/bios/bios.bin.elf
+	$(E) "  NM      " $@
+	$(Q) cd x86/bios && sh gen-offsets.sh > bios-rom.h && cd ..
+
+check: all
+	$(MAKE) -C tests
+	./$(PROGRAM) run tests/pit/tick.bin
+	./$(PROGRAM) run -d tests/boot/boot_test.iso -p "init=init"
+.PHONY: check
+
+clean:
+	$(E) "  CLEAN"
+	$(Q) rm -f x86/bios/*.bin
+	$(Q) rm -f x86/bios/*.elf
+	$(Q) rm -f x86/bios/*.o
+	$(Q) rm -f x86/bios/bios-rom.h
+	$(Q) rm -f tests/boot/boot_test.iso
+	$(Q) rm -rf tests/boot/rootfs/
+	$(Q) rm -f $(DEPS) $(OBJS) $(PROGRAM) $(PROGRAM_ALIAS) $(GUEST_INIT) $(GUEST_INIT_S2)
+	$(Q) rm -f cscope.*
+	$(Q) rm -f tags
+	$(Q) rm -f TAGS
+	$(Q) rm -f $(KVM_INCLUDE)/common-cmds.h
+	$(Q) rm -f KVMTOOLS-VERSION-FILE
+.PHONY: clean
+
+KVM_DEV	?= /dev/kvm
+
+$(KVM_DEV):
+	$(E) "  MKNOD " $@
+	$(Q) mknod $@ char 10 232
+
+devices: $(KVM_DEV)
+.PHONY: devices
+
+TAGS:
+	$(E) "  GEN" $@
+	$(Q) $(RM) -f TAGS
+	$(Q) $(FIND) . -name '*.[hcS]' -print | xargs etags -a
+.PHONY: TAGS
+
+tags:
+	$(E) "  GEN" $@
+	$(Q) $(RM) -f tags
+	$(Q) $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
+.PHONY: tags
+
+cscope:
+	$(E) "  GEN" $@
+	$(Q) $(FIND) . -name '*.[hcS]' -print > cscope.files
+	$(Q) $(CSCOPE) -bkqu
+.PHONY: cscope
+
+# Deps
+-include $(DEPS)
diff --git a/tools/kvm/README b/tools/kvm/README
new file mode 100644
index 0000000..d626b77
--- /dev/null
+++ b/tools/kvm/README
@@ -0,0 +1,109 @@
+Native Linux KVM tool
+=====================
+The goal of this tool is to provide a clean, from-scratch, lightweight
+KVM host tool implementation that can boot Linux guest images (just a
+hobby, won't be big and professional like QEMU) with no BIOS
+dependencies and with only the minimal amount of legacy device
+emulation.
+
+It's great as a learning tool if you want to get your feet wet in
+virtualization land: it's only 5 KLOC of clean C code that can already
+boot a guest Linux image.
+
+Right now it can boot a Linux image and provide you output via a serial
+console, over the host terminal, i.e. you can use it to boot a guest
+Linux image in a terminal or over ssh and log into the guest without
+much guest or host side setup work needed.
+
+1. To try out the tool, clone the git repository:
+
+  git clone git://github.com/penberg/linux-kvm.git
+
+or alternatively, if you already have a kernel source tree:
+
+  git remote add kvm-tool git://github.com/penberg/linux-kvm.git
+  git remote update
+  git checkout -b kvm-tool/master kvm-tool
+
+2. Compile the tool:
+
+  cd tools/kvm && make
+
+3. Download a raw userspace image:
+
+  wget http://wiki.qemu.org/download/linux-0.2.img.bz2 && bunzip2
+linux-0.2.img.bz2
+
+4. The guest kernel has to be built with the following configuration:
+
+ - For the default console output:
+	CONFIG_SERIAL_8250=y
+	CONFIG_SERIAL_8250_CONSOLE=y
+
+ - For running 32bit images on 64bit hosts:
+	CONFIG_IA32_EMULATION=y
+
+ - Proper FS options according to image FS (e.g. CONFIG_EXT2_FS, CONFIG_EXT4_FS).
+
+ - For all virtio devices listed below:
+	CONFIG_VIRTIO=y
+	CONFIG_VIRTIO_RING=y
+	CONFIG_VIRTIO_PCI=y
+
+ - For virtio-blk devices (--disk, -d):
+	CONFIG_VIRTIO_BLK=y
+
+ - For virtio-net devices ([--network, -n] virtio):
+	CONFIG_VIRTIO_NET=y
+
+ - For virtio-9p devices (--virtio-9p):
+	CONFIG_NET_9P=y
+	CONFIG_NET_9P_VIRTIO=y
+	CONFIG_9P_FS=y
+
+ - For virtio-balloon device (--balloon):
+	CONFIG_VIRTIO_BALLOON=y
+
+ - For virtio-console device (--console virtio):
+	CONFIG_VIRTIO_CONSOLE=y
+
+ - For virtio-rng device (--rng):
+	CONFIG_HW_RANDOM_VIRTIO=y
+
+
+5. And finally, launch the hypervisor:
+
+  ./lkvm run --disk linux-0.2.img \
+	    --kernel ../../arch/x86/boot/bzImage \
+or
+
+  sudo ./lkvm run --disk linux-0.2.img \
+		 --kernel ../../arch/x86/boot/bzImage \
+		 --network virtio
+
+The tool has been written by Pekka Enberg, Cyrill Gorcunov, Asias He,
+Sasha Levin and Prasad Joshi. Special thanks to Avi Kivity for his help
+on KVM internals and Ingo Molnar for all-around support and encouragement!
+
+See the following thread for original discussion for motivation of this
+project:
+
+http://thread.gmane.org/gmane.linux.kernel/962051/focus=962620
+
+Build dependencies
+=====================
+For deb based systems:
+32-bit:
+sudo apt-get install build-essential
+64-bit:
+sudo apt-get install build-essential libc6-dev-i386
+
+For rpm based systems:
+32-bit:
+yum install glibc-devel
+64-bit:
+yum install glibc-devel glibc-static
+
+On 64-bit Arch Linux make sure the multilib repository is enabled in your
+/etc/pacman.conf and run
+pacman -Sy lib32-glibc
diff --git a/tools/kvm/builtin-balloon.c b/tools/kvm/builtin-balloon.c
new file mode 100644
index 0000000..5bd2291
--- /dev/null
+++ b/tools/kvm/builtin-balloon.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-balloon.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm.h>
+#include <kvm/kvm-ipc.h>
+
+static const char *instance_name;
+static u64 inflate;
+static u64 deflate;
+
+static const char * const balloon_usage[] = {
+	"lkvm balloon [-n name] [-p pid] [-i amount] [-d amount]",
+	NULL
+};
+
+static const struct option balloon_options[] = {
+	OPT_GROUP("Instance options:"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_GROUP("Balloon options:"),
+	OPT_U64('i', "inflate", &inflate, "Amount to inflate"),
+	OPT_U64('d', "deflate", &deflate, "Amount to deflate"),
+	OPT_END(),
+};
+
+void kvm_balloon_help(void)
+{
+	usage_with_options(balloon_usage, balloon_options);
+}
+
+static void parse_balloon_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, balloon_options, balloon_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_balloon_help();
+	}
+}
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix)
+{
+	int instance;
+	int r;
+	int amount;
+
+	parse_balloon_options(argc, argv);
+
+	if (inflate == 0 && deflate == 0)
+		kvm_balloon_help();
+
+	if (instance_name == NULL)
+		kvm_balloon_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	if (inflate)
+		amount = inflate;
+	else if (deflate)
+		amount = -deflate;
+	else
+		kvm_balloon_help();
+
+	r = kvm_ipc__send_msg(instance, KVM_IPC_BALLOON,
+			sizeof(amount), (u8 *)&amount);
+
+	close(instance);
+
+	if (r < 0)
+		return -1;
+
+	return 0;
+}
diff --git a/tools/kvm/builtin-debug.c b/tools/kvm/builtin-debug.c
new file mode 100644
index 0000000..20e27ff
--- /dev/null
+++ b/tools/kvm/builtin-debug.c
@@ -0,0 +1,103 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-debug.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+#include <kvm/read-write.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#define BUFFER_SIZE 100
+
+static bool all;
+static int nmi = -1;
+static bool dump;
+static const char *instance_name;
+
+static const char * const debug_usage[] = {
+	"lkvm debug [--all] [-n name] [-d] [-m vcpu]",
+	NULL
+};
+
+static const struct option debug_options[] = {
+	OPT_GROUP("General options:"),
+	OPT_BOOLEAN('d', "dump", &dump, "Generate a debug dump from guest"),
+	OPT_INTEGER('m', "nmi", &nmi, "Generate NMI on VCPU"),
+	OPT_GROUP("Instance options:"),
+	OPT_BOOLEAN('a', "all", &all, "Debug all instances"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_END()
+};
+
+static void parse_debug_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, debug_options, debug_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_debug_help();
+	}
+}
+
+void kvm_debug_help(void)
+{
+	usage_with_options(debug_usage, debug_options);
+}
+
+static int do_debug(const char *name, int sock)
+{
+	char buff[BUFFER_SIZE];
+	struct debug_cmd_params cmd = {.dbg_type = 0};
+	int r;
+
+	if (dump)
+		cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_DUMP;
+
+	if (nmi != -1) {
+		cmd.dbg_type |= KVM_DEBUG_CMD_TYPE_NMI;
+		cmd.cpu = nmi;
+	}
+
+	r = kvm_ipc__send_msg(sock, KVM_IPC_DEBUG, sizeof(cmd), (u8 *)&cmd);
+	if (r < 0)
+		return r;
+
+	if (!dump)
+		return 0;
+
+	do {
+		r = xread(sock, buff, BUFFER_SIZE);
+		if (r < 0)
+			return 0;
+		printf("%.*s", r, buff);
+	} while (r > 0);
+
+	return 0;
+}
+
+int kvm_cmd_debug(int argc, const char **argv, const char *prefix)
+{
+	parse_debug_options(argc, argv);
+	int instance;
+	int r;
+
+	if (all)
+		return kvm__enumerate_instances(do_debug);
+
+	if (instance_name == NULL)
+		kvm_debug_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	r = do_debug(instance_name, instance);
+
+	close(instance);
+
+	return r;
+}
diff --git a/tools/kvm/builtin-help.c b/tools/kvm/builtin-help.c
new file mode 100644
index 0000000..5970fb7
--- /dev/null
+++ b/tools/kvm/builtin-help.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <string.h>
+
+/* user defined headers */
+#include <common-cmds.h>
+
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-help.h>
+#include <kvm/kvm.h>
+
+
+const char kvm_usage_string[] =
+	"lkvm COMMAND [ARGS]";
+
+const char kvm_more_info_string[] =
+	"See 'lkvm help COMMAND' for more information on a specific command.";
+
+
+static void list_common_cmds_help(void)
+{
+	unsigned int i, longest = 0;
+
+	for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+		if (longest < strlen(common_cmds[i].name))
+			longest = strlen(common_cmds[i].name);
+	}
+
+	puts(" The most commonly used lkvm commands are:");
+	for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+		printf("   %-*s   ", longest, common_cmds[i].name);
+		puts(common_cmds[i].help);
+	}
+}
+
+static void kvm_help(void)
+{
+	printf("\n To start a simple non-privileged shell run '%s run'\n\n"
+		"usage: %s\n\n", KVM_BINARY_NAME, kvm_usage_string);
+	list_common_cmds_help();
+	printf("\n %s\n\n", kvm_more_info_string);
+}
+
+
+static void help_cmd(const char *cmd)
+{
+	struct cmd_struct *p;
+	p = kvm_get_command(kvm_commands, cmd);
+	if (!p)
+		kvm_help();
+	else if (p->help)
+		p->help();
+}
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix)
+{
+	if (!argv || !*argv) {
+		kvm_help();
+		return 0;
+	}
+	help_cmd(argv[0]);
+	return 0;
+}
diff --git a/tools/kvm/builtin-list.c b/tools/kvm/builtin-list.c
new file mode 100644
index 0000000..9299f17
--- /dev/null
+++ b/tools/kvm/builtin-list.c
@@ -0,0 +1,149 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+
+static bool run;
+static bool rootfs;
+
+static const char * const list_usage[] = {
+	"lkvm list",
+	NULL
+};
+
+static const struct option list_options[] = {
+	OPT_GROUP("General options:"),
+	OPT_BOOLEAN('i', "run", &run, "List running instances"),
+	OPT_BOOLEAN('r', "rootfs", &rootfs, "List rootfs instances"),
+	OPT_END()
+};
+
+#define KVM_INSTANCE_RUNNING	"running"
+#define KVM_INSTANCE_PAUSED	"paused"
+#define KVM_INSTANCE_SHUTOFF	"shut off"
+
+void kvm_list_help(void)
+{
+	usage_with_options(list_usage, list_options);
+}
+
+static pid_t get_pid(int sock)
+{
+	pid_t pid;
+	int r;
+
+	r = kvm_ipc__send(sock, KVM_IPC_PID);
+	if (r < 0)
+		return r;
+
+	r = read(sock, &pid, sizeof(pid));
+	if (r < 0)
+		return r;
+
+	return pid;
+}
+
+int get_vmstate(int sock)
+{
+	int vmstate;
+	int r;
+
+	r = kvm_ipc__send(sock, KVM_IPC_VMSTATE);
+	if (r < 0)
+		return r;
+
+	r = read(sock, &vmstate, sizeof(vmstate));
+	if (r < 0)
+		return r;
+
+	return vmstate;
+
+}
+
+static int print_guest(const char *name, int sock)
+{
+	pid_t pid;
+	int vmstate;
+
+	pid = get_pid(sock);
+	vmstate = get_vmstate(sock);
+
+	if ((int)pid < 0 || vmstate < 0)
+		return -1;
+
+	if (vmstate == KVM_VMSTATE_PAUSED)
+		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_PAUSED);
+	else
+		printf("%5d %-20s %s\n", pid, name, KVM_INSTANCE_RUNNING);
+
+	return 0;
+}
+
+static int kvm_list_running_instances(void)
+{
+	return kvm__enumerate_instances(print_guest);
+}
+
+static int kvm_list_rootfs(void)
+{
+	DIR *dir;
+	struct dirent *dirent;
+
+	dir = opendir(kvm__get_dir());
+	if (dir == NULL)
+		return -1;
+
+	while ((dirent = readdir(dir))) {
+		if (dirent->d_type == DT_DIR &&
+			strcmp(dirent->d_name, ".") &&
+			strcmp(dirent->d_name, ".."))
+			printf("%5s %-20s %s\n", "", dirent->d_name, KVM_INSTANCE_SHUTOFF);
+	}
+
+	return 0;
+}
+
+static void parse_setup_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, list_options, list_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_list_help();
+	}
+}
+
+int kvm_cmd_list(int argc, const char **argv, const char *prefix)
+{
+	int r;
+
+	parse_setup_options(argc, argv);
+
+	if (!run && !rootfs)
+		run = rootfs = true;
+
+	printf("%6s %-20s %s\n", "PID", "NAME", "STATE");
+	printf("------------------------------------\n");
+
+	if (run) {
+		r = kvm_list_running_instances();
+		if (r < 0)
+			perror("Error listing instances");
+	}
+
+	if (rootfs) {
+		r = kvm_list_rootfs();
+		if (r < 0)
+			perror("Error listing rootfs");
+	}
+
+	return 0;
+}
diff --git a/tools/kvm/builtin-pause.c b/tools/kvm/builtin-pause.c
new file mode 100644
index 0000000..c08595a
--- /dev/null
+++ b/tools/kvm/builtin-pause.c
@@ -0,0 +1,88 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-pause.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const pause_usage[] = {
+	"lkvm pause [--all] [-n name]",
+	NULL
+};
+
+static const struct option pause_options[] = {
+	OPT_GROUP("General options:"),
+	OPT_BOOLEAN('a', "all", &all, "Pause all instances"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_END()
+};
+
+static void parse_pause_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, pause_options, pause_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_pause_help();
+	}
+}
+
+void kvm_pause_help(void)
+{
+	usage_with_options(pause_usage, pause_options);
+}
+
+static int do_pause(const char *name, int sock)
+{
+	int r;
+	int vmstate;
+
+	vmstate = get_vmstate(sock);
+	if (vmstate < 0)
+		return vmstate;
+	if (vmstate == KVM_VMSTATE_PAUSED) {
+		printf("Guest %s is already paused.\n", name);
+		return 0;
+	}
+
+	r = kvm_ipc__send(sock, KVM_IPC_PAUSE);
+	if (r)
+		return r;
+
+	printf("Guest %s paused\n", name);
+
+	return 0;
+}
+
+int kvm_cmd_pause(int argc, const char **argv, const char *prefix)
+{
+	int instance;
+	int r;
+
+	parse_pause_options(argc, argv);
+
+	if (all)
+		return kvm__enumerate_instances(do_pause);
+
+	if (instance_name == NULL)
+		kvm_pause_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	r = do_pause(instance_name, instance);
+
+	close(instance);
+
+	return r;
+}
diff --git a/tools/kvm/builtin-resume.c b/tools/kvm/builtin-resume.c
new file mode 100644
index 0000000..0e954b4
--- /dev/null
+++ b/tools/kvm/builtin-resume.c
@@ -0,0 +1,88 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-resume.h>
+#include <kvm/builtin-list.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const resume_usage[] = {
+	"lkvm resume [--all] [-n name]",
+	NULL
+};
+
+static const struct option resume_options[] = {
+	OPT_GROUP("General options:"),
+	OPT_BOOLEAN('a', "all", &all, "Resume all instances"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_END()
+};
+
+static void parse_resume_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, resume_options, resume_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_resume_help();
+	}
+}
+
+void kvm_resume_help(void)
+{
+	usage_with_options(resume_usage, resume_options);
+}
+
+static int do_resume(const char *name, int sock)
+{
+	int r;
+	int vmstate;
+
+	vmstate = get_vmstate(sock);
+	if (vmstate < 0)
+		return vmstate;
+	if (vmstate == KVM_VMSTATE_RUNNING) {
+		printf("Guest %s is still running.\n", name);
+		return 0;
+	}
+
+	r = kvm_ipc__send(sock, KVM_IPC_RESUME);
+	if (r)
+		return r;
+
+	printf("Guest %s resumed\n", name);
+
+	return 0;
+}
+
+int kvm_cmd_resume(int argc, const char **argv, const char *prefix)
+{
+	int instance;
+	int r;
+
+	parse_resume_options(argc, argv);
+
+	if (all)
+		return kvm__enumerate_instances(do_resume);
+
+	if (instance_name == NULL)
+		kvm_resume_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	r = do_resume(instance_name, instance);
+
+	close(instance);
+
+	return r;
+}
diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
new file mode 100644
index 0000000..802449c
--- /dev/null
+++ b/tools/kvm/builtin-run.c
@@ -0,0 +1,1218 @@
+#include "kvm/builtin-run.h"
+
+#include "kvm/builtin-setup.h"
+#include "kvm/virtio-balloon.h"
+#include "kvm/virtio-console.h"
+#include "kvm/parse-options.h"
+#include "kvm/8250-serial.h"
+#include "kvm/framebuffer.h"
+#include "kvm/disk-image.h"
+#include "kvm/threadpool.h"
+#include "kvm/virtio-blk.h"
+#include "kvm/virtio-net.h"
+#include "kvm/virtio-rng.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/virtio-9p.h"
+#include "kvm/barrier.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/ioport.h"
+#include "kvm/symbol.h"
+#include "kvm/i8042.h"
+#include "kvm/mutex.h"
+#include "kvm/term.h"
+#include "kvm/util.h"
+#include "kvm/strbuf.h"
+#include "kvm/vesa.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/rtc.h"
+#include "kvm/sdl.h"
+#include "kvm/vnc.h"
+#include "kvm/guest_compat.h"
+#include "kvm/pci-shmem.h"
+#include "kvm/kvm-ipc.h"
+#include "kvm/builtin-debug.h"
+
+#include <linux/types.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#define DEFAULT_KVM_DEV		"/dev/kvm"
+#define DEFAULT_CONSOLE		"serial"
+#define DEFAULT_NETWORK		"user"
+#define DEFAULT_HOST_ADDR	"192.168.33.1"
+#define DEFAULT_GUEST_ADDR	"192.168.33.15"
+#define DEFAULT_GUEST_MAC	"02:15:15:15:15:15"
+#define DEFAULT_HOST_MAC	"02:01:01:01:01:01"
+#define DEFAULT_SCRIPT		"none"
+const char *DEFAULT_SANDBOX_FILENAME = "guest/sandbox.sh";
+
+#define MB_SHIFT		(20)
+#define KB_SHIFT		(10)
+#define GB_SHIFT		(30)
+#define MIN_RAM_SIZE_MB		(64ULL)
+#define MIN_RAM_SIZE_BYTE	(MIN_RAM_SIZE_MB << MB_SHIFT)
+
+struct kvm *kvm;
+struct kvm_cpu **kvm_cpus;
+__thread struct kvm_cpu *current_kvm_cpu;
+
+static u64 ram_size;
+static u8  image_count;
+static u8 num_net_devices;
+static bool virtio_rng;
+static const char *kernel_cmdline;
+static const char *kernel_filename;
+static const char *vmlinux_filename;
+static const char *initrd_filename;
+static const char *image_filename[MAX_DISK_IMAGES];
+static const char *console;
+static const char *dev;
+static const char *network;
+static const char *host_ip;
+static const char *guest_ip;
+static const char *guest_mac;
+static const char *host_mac;
+static const char *script;
+static const char *guest_name;
+static const char *sandbox;
+static const char *hugetlbfs_path;
+static const char *custom_rootfs_name = "default";
+static struct virtio_net_params *net_params;
+static bool single_step;
+static bool readonly_image[MAX_DISK_IMAGES];
+static bool vnc;
+static bool sdl;
+static bool balloon;
+static bool using_rootfs;
+static bool custom_rootfs;
+static bool no_net;
+static bool no_dhcp;
+extern bool ioport_debug;
+static int  kvm_run_wrapper;
+extern int  active_console;
+extern int  debug_iodelay;
+
+bool do_debug_print = false;
+
+static int nrcpus;
+static int vidmode = -1;
+
+static const char * const run_usage[] = {
+	"lkvm run [<options>] [<kernel image>]",
+	NULL
+};
+
+enum {
+	KVM_RUN_DEFAULT,
+	KVM_RUN_SANDBOX,
+};
+
+void kvm_run_set_wrapper_sandbox(void)
+{
+	kvm_run_wrapper = KVM_RUN_SANDBOX;
+}
+
+static int img_name_parser(const struct option *opt, const char *arg, int unset)
+{
+	char *sep;
+	struct stat st;
+	char path[PATH_MAX];
+
+	if (stat(arg, &st) == 0 &&
+	    S_ISDIR(st.st_mode)) {
+		char tmp[PATH_MAX];
+
+		if (using_rootfs)
+			die("Please use only one rootfs directory atmost");
+
+		if (realpath(arg, tmp) == 0 ||
+		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+			die("Unable to initialize virtio 9p");
+		using_rootfs = 1;
+		return 0;
+	}
+
+	snprintf(path, PATH_MAX, "%s%s", kvm__get_dir(), arg);
+
+	if (stat(path, &st) == 0 &&
+	    S_ISDIR(st.st_mode)) {
+		char tmp[PATH_MAX];
+
+		if (using_rootfs)
+			die("Please use only one rootfs directory atmost");
+
+		if (realpath(path, tmp) == 0 ||
+		    virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+			die("Unable to initialize virtio 9p");
+		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
+			die("Unable to initialize virtio 9p");
+		kvm_setup_resolv(arg);
+		using_rootfs = custom_rootfs = 1;
+		custom_rootfs_name = arg;
+		return 0;
+	}
+
+	if (image_count >= MAX_DISK_IMAGES)
+		die("Currently only 4 images are supported");
+
+	image_filename[image_count] = arg;
+	sep = strstr(arg, ",");
+	if (sep) {
+		if (strcmp(sep + 1, "ro") == 0)
+			readonly_image[image_count] = 1;
+		*sep = 0;
+	}
+
+	image_count++;
+
+	return 0;
+}
+
+static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, int unset)
+{
+	char *tag_name;
+	char tmp[PATH_MAX];
+
+	/*
+	 * 9p dir can be of the form dirname,tag_name or
+	 * just dirname. In the later case we use the
+	 * default tag name
+	 */
+	tag_name = strstr(arg, ",");
+	if (tag_name) {
+		*tag_name = '\0';
+		tag_name++;
+	}
+	if (realpath(arg, tmp)) {
+		if (virtio_9p__register(kvm, tmp, tag_name) < 0)
+			die("Unable to initialize virtio 9p");
+	} else
+		die("Failed resolving 9p path");
+	return 0;
+}
+
+static int tty_parser(const struct option *opt, const char *arg, int unset)
+{
+	int tty = atoi(arg);
+
+	term_set_tty(tty);
+
+	return 0;
+}
+
+static inline void str_to_mac(const char *str, char *mac)
+{
+	sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+		mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+}
+static int set_net_param(struct virtio_net_params *p, const char *param,
+				const char *val)
+{
+	if (strcmp(param, "guest_mac") == 0) {
+		str_to_mac(val, p->guest_mac);
+	} else if (strcmp(param, "mode") == 0) {
+		if (!strncmp(val, "user", 4)) {
+			int i;
+
+			for (i = 0; i < num_net_devices; i++)
+				if (net_params[i].mode == NET_MODE_USER)
+					die("Only one usermode network device allowed at a time");
+			p->mode = NET_MODE_USER;
+		} else if (!strncmp(val, "tap", 3)) {
+			p->mode = NET_MODE_TAP;
+		} else if (!strncmp(val, "none", 4)) {
+			no_net = 1;
+			return -1;
+		} else
+			die("Unkown network mode %s, please use user, tap or none", network);
+	} else if (strcmp(param, "script") == 0) {
+		p->script = strdup(val);
+	} else if (strcmp(param, "guest_ip") == 0) {
+		p->guest_ip = strdup(val);
+	} else if (strcmp(param, "host_ip") == 0) {
+		p->host_ip = strdup(val);
+	} else if (strcmp(param, "vhost") == 0) {
+		p->vhost = atoi(val);
+	} else if (strcmp(param, "fd") == 0) {
+		p->fd = atoi(val);
+	}
+
+	return 0;
+}
+
+static int netdev_parser(const struct option *opt, const char *arg, int unset)
+{
+	struct virtio_net_params p;
+	char *buf = NULL, *cmd = NULL, *cur = NULL;
+	bool on_cmd = true;
+
+	if (arg) {
+		buf = strdup(arg);
+		if (buf == NULL)
+			die("Failed allocating new net buffer");
+		cur = strtok(buf, ",=");
+	}
+
+	p = (struct virtio_net_params) {
+		.guest_ip	= DEFAULT_GUEST_ADDR,
+		.host_ip	= DEFAULT_HOST_ADDR,
+		.script		= DEFAULT_SCRIPT,
+		.mode		= NET_MODE_TAP,
+	};
+
+	str_to_mac(DEFAULT_GUEST_MAC, p.guest_mac);
+	p.guest_mac[5] += num_net_devices;
+
+	while (cur) {
+		if (on_cmd) {
+			cmd = cur;
+		} else {
+			if (set_net_param(&p, cmd, cur) < 0)
+				goto done;
+		}
+		on_cmd = !on_cmd;
+
+		cur = strtok(NULL, ",=");
+	};
+
+	num_net_devices++;
+
+	net_params = realloc(net_params, num_net_devices * sizeof(*net_params));
+	if (net_params == NULL)
+		die("Failed adding new network device");
+
+	net_params[num_net_devices - 1] = p;
+
+done:
+	free(buf);
+	return 0;
+}
+
+static int shmem_parser(const struct option *opt, const char *arg, int unset)
+{
+	const u64 default_size = SHMEM_DEFAULT_SIZE;
+	const u64 default_phys_addr = SHMEM_DEFAULT_ADDR;
+	const char *default_handle = SHMEM_DEFAULT_HANDLE;
+	struct shmem_info *si = malloc(sizeof(struct shmem_info));
+	u64 phys_addr;
+	u64 size;
+	char *handle = NULL;
+	int create = 0;
+	const char *p = arg;
+	char *next;
+	int base = 10;
+	int verbose = 0;
+
+	const int skip_pci = strlen("pci:");
+	if (verbose)
+		pr_info("shmem_parser(%p,%s,%d)", opt, arg, unset);
+	/* parse out optional addr family */
+	if (strcasestr(p, "pci:")) {
+		p += skip_pci;
+	} else if (strcasestr(p, "mem:")) {
+		die("I can't add to E820 map yet.\n");
+	}
+	/* parse out physical addr */
+	base = 10;
+	if (strcasestr(p, "0x"))
+		base = 16;
+	phys_addr = strtoll(p, &next, base);
+	if (next == p && phys_addr == 0) {
+		pr_info("shmem: no physical addr specified, using default.");
+		phys_addr = default_phys_addr;
+	}
+	if (*next != ':' && *next != '\0')
+		die("shmem: unexpected chars after phys addr.\n");
+	if (*next == '\0')
+		p = next;
+	else
+		p = next + 1;
+	/* parse out size */
+	base = 10;
+	if (strcasestr(p, "0x"))
+		base = 16;
+	size = strtoll(p, &next, base);
+	if (next == p && size == 0) {
+		pr_info("shmem: no size specified, using default.");
+		size = default_size;
+	}
+	/* look for [KMGkmg][Bb]*  uses base 2. */
+	int skip_B = 0;
+	if (strspn(next, "KMGkmg")) {	/* might have a prefix */
+		if (*(next + 1) == 'B' || *(next + 1) == 'b')
+			skip_B = 1;
+		switch (*next) {
+		case 'K':
+		case 'k':
+			size = size << KB_SHIFT;
+			break;
+		case 'M':
+		case 'm':
+			size = size << MB_SHIFT;
+			break;
+		case 'G':
+		case 'g':
+			size = size << GB_SHIFT;
+			break;
+		default:
+			die("shmem: bug in detecting size prefix.");
+			break;
+		}
+		next += 1 + skip_B;
+	}
+	if (*next != ':' && *next != '\0') {
+		die("shmem: unexpected chars after phys size. <%c><%c>\n",
+		    *next, *p);
+	}
+	if (*next == '\0')
+		p = next;
+	else
+		p = next + 1;
+	/* parse out optional shmem handle */
+	const int skip_handle = strlen("handle=");
+	next = strcasestr(p, "handle=");
+	if (*p && next) {
+		if (p != next)
+			die("unexpected chars before handle\n");
+		p += skip_handle;
+		next = strchrnul(p, ':');
+		if (next - p) {
+			handle = malloc(next - p + 1);
+			strncpy(handle, p, next - p);
+			handle[next - p] = '\0';	/* just in case. */
+		}
+		if (*next == '\0')
+			p = next;
+		else
+			p = next + 1;
+	}
+	/* parse optional create flag to see if we should create shm seg. */
+	if (*p && strcasestr(p, "create")) {
+		create = 1;
+		p += strlen("create");
+	}
+	if (*p != '\0')
+		die("shmem: unexpected trailing chars\n");
+	if (handle == NULL) {
+		handle = malloc(strlen(default_handle) + 1);
+		strcpy(handle, default_handle);
+	}
+	if (verbose) {
+		pr_info("shmem: phys_addr = %llx", phys_addr);
+		pr_info("shmem: size      = %llx", size);
+		pr_info("shmem: handle    = %s", handle);
+		pr_info("shmem: create    = %d", create);
+	}
+
+	si->phys_addr = phys_addr;
+	si->size = size;
+	si->handle = handle;
+	si->create = create;
+	pci_shmem__register_mem(si);	/* ownership of si, etc. passed on. */
+	return 0;
+}
+
+static const struct option options[] = {
+	OPT_GROUP("Basic options:"),
+	OPT_STRING('\0', "name", &guest_name, "guest name",
+			"A name for the guest"),
+	OPT_INTEGER('c', "cpus", &nrcpus, "Number of CPUs"),
+	OPT_U64('m', "mem", &ram_size, "Virtual machine memory size in MiB."),
+	OPT_CALLBACK('\0', "shmem", NULL,
+		     "[pci:]<addr>:<size>[:handle=<handle>][:create]",
+		     "Share host shmem with guest via pci device",
+		     shmem_parser),
+	OPT_CALLBACK('d', "disk", NULL, "image or rootfs_dir", "Disk image or rootfs directory", img_name_parser),
+	OPT_BOOLEAN('\0', "balloon", &balloon, "Enable virtio balloon"),
+	OPT_BOOLEAN('\0', "vnc", &vnc, "Enable VNC framebuffer"),
+	OPT_BOOLEAN('\0', "sdl", &sdl, "Enable SDL framebuffer"),
+	OPT_BOOLEAN('\0', "rng", &virtio_rng, "Enable virtio Random Number Generator"),
+	OPT_CALLBACK('\0', "9p", NULL, "dir_to_share,tag_name",
+		     "Enable virtio 9p to share files between host and guest", virtio_9p_rootdir_parser),
+	OPT_STRING('\0', "console", &console, "serial, virtio or hv",
+			"Console to use"),
+	OPT_STRING('\0', "dev", &dev, "device_file", "KVM device file"),
+	OPT_CALLBACK('\0', "tty", NULL, "tty id",
+		     "Remap guest TTY into a pty on the host",
+		     tty_parser),
+	OPT_STRING('\0', "sandbox", &sandbox, "script",
+			"Run this script when booting into custom rootfs"),
+	OPT_STRING('\0', "hugetlbfs", &hugetlbfs_path, "path", "Hugetlbfs path"),
+
+	OPT_GROUP("Kernel options:"),
+	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
+			"Kernel to boot in virtual machine"),
+	OPT_STRING('i', "initrd", &initrd_filename, "initrd",
+			"Initial RAM disk image"),
+	OPT_STRING('p', "params", &kernel_cmdline, "params",
+			"Kernel command line arguments"),
+
+	OPT_GROUP("Networking options:"),
+	OPT_CALLBACK_DEFAULT('n', "network", NULL, "network params",
+		     "Create a new guest NIC",
+		     netdev_parser, NULL),
+	OPT_BOOLEAN('\0', "no-dhcp", &no_dhcp, "Disable kernel DHCP in rootfs mode"),
+
+	OPT_GROUP("BIOS options:"),
+	OPT_INTEGER('\0', "vidmode", &vidmode,
+		    "Video mode"),
+
+	OPT_GROUP("Debug options:"),
+	OPT_BOOLEAN('\0', "debug", &do_debug_print,
+			"Enable debug messages"),
+	OPT_BOOLEAN('\0', "debug-single-step", &single_step,
+			"Enable single stepping"),
+	OPT_BOOLEAN('\0', "debug-ioport", &ioport_debug,
+			"Enable ioport debugging"),
+	OPT_INTEGER('\0', "debug-iodelay", &debug_iodelay,
+			"Delay IO by millisecond"),
+	OPT_END()
+};
+
+/*
+ * Serialize debug printout so that the output of multiple vcpus does not
+ * get mixed up:
+ */
+static int printout_done;
+
+static void handle_sigusr1(int sig)
+{
+	struct kvm_cpu *cpu = current_kvm_cpu;
+	int fd = kvm_cpu__get_debug_fd();
+
+	if (!cpu || cpu->needs_nmi)
+		return;
+
+	dprintf(fd, "\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
+	kvm_cpu__show_registers(cpu);
+	kvm_cpu__show_code(cpu);
+	kvm_cpu__show_page_tables(cpu);
+	fflush(stdout);
+	printout_done = 1;
+	mb();
+}
+
+/* Pause/resume the guest using SIGUSR2 */
+static int is_paused;
+
+static void handle_pause(int fd, u32 type, u32 len, u8 *msg)
+{
+	if (WARN_ON(len))
+		return;
+
+	if (type == KVM_IPC_RESUME && is_paused) {
+		kvm->vm_state = KVM_VMSTATE_RUNNING;
+		kvm__continue();
+	} else if (type == KVM_IPC_PAUSE && !is_paused) {
+		kvm->vm_state = KVM_VMSTATE_PAUSED;
+		kvm__pause();
+	} else {
+		return;
+	}
+
+	is_paused = !is_paused;
+}
+
+static void handle_vmstate(int fd, u32 type, u32 len, u8 *msg)
+{
+	int r = 0;
+
+	if (type == KVM_IPC_VMSTATE)
+		r = write(fd, &kvm->vm_state, sizeof(kvm->vm_state));
+
+	if (r < 0)
+		pr_warning("Failed sending VMSTATE");
+}
+
+static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
+{
+	int i;
+	struct debug_cmd_params *params;
+	u32 dbg_type;
+	u32 vcpu;
+
+	if (WARN_ON(type != KVM_IPC_DEBUG || len != sizeof(*params)))
+		return;
+
+	params = (void *)msg;
+	dbg_type = params->dbg_type;
+	vcpu = params->cpu;
+
+	if (dbg_type & KVM_DEBUG_CMD_TYPE_NMI) {
+		if ((int)vcpu >= kvm->nrcpus)
+			return;
+
+		kvm_cpus[vcpu]->needs_nmi = 1;
+		pthread_kill(kvm_cpus[vcpu]->thread, SIGUSR1);
+	}
+
+	if (!(dbg_type & KVM_DEBUG_CMD_TYPE_DUMP))
+		return;
+
+	for (i = 0; i < nrcpus; i++) {
+		struct kvm_cpu *cpu = kvm_cpus[i];
+
+		if (!cpu)
+			continue;
+
+		printout_done = 0;
+
+		kvm_cpu__set_debug_fd(fd);
+		pthread_kill(cpu->thread, SIGUSR1);
+		/*
+		 * Wait for the vCPU to dump state before signalling
+		 * the next thread. Since this is debug code it does
+		 * not matter that we are burning CPU time a bit:
+		 */
+		while (!printout_done)
+			mb();
+	}
+
+	close(fd);
+
+	serial8250__inject_sysrq(kvm);
+}
+
+static void handle_sigalrm(int sig)
+{
+	kvm__arch_periodic_poll(kvm);
+}
+
+static void handle_stop(int fd, u32 type, u32 len, u8 *msg)
+{
+	if (WARN_ON(type != KVM_IPC_STOP || len))
+		return;
+
+	kvm_cpu__reboot();
+}
+
+static void *kvm_cpu_thread(void *arg)
+{
+	current_kvm_cpu		= arg;
+
+	if (kvm_cpu__start(current_kvm_cpu))
+		goto panic_kvm;
+
+	return (void *) (intptr_t) 0;
+
+panic_kvm:
+	fprintf(stderr, "KVM exit reason: %u (\"%s\")\n",
+		current_kvm_cpu->kvm_run->exit_reason,
+		kvm_exit_reasons[current_kvm_cpu->kvm_run->exit_reason]);
+	if (current_kvm_cpu->kvm_run->exit_reason == KVM_EXIT_UNKNOWN)
+		fprintf(stderr, "KVM exit code: 0x%Lu\n",
+			current_kvm_cpu->kvm_run->hw.hardware_exit_reason);
+
+	kvm_cpu__set_debug_fd(STDOUT_FILENO);
+	kvm_cpu__show_registers(current_kvm_cpu);
+	kvm_cpu__show_code(current_kvm_cpu);
+	kvm_cpu__show_page_tables(current_kvm_cpu);
+
+	return (void *) (intptr_t) 1;
+}
+
+static char kernel[PATH_MAX];
+
+static const char *host_kernels[] = {
+	"/boot/vmlinuz",
+	"/boot/bzImage",
+	NULL
+};
+
+static const char *default_kernels[] = {
+	"./bzImage",
+	"arch/" BUILD_ARCH "/boot/bzImage",
+	"../../arch/" BUILD_ARCH "/boot/bzImage",
+	NULL
+};
+
+static const char *default_vmlinux[] = {
+	"vmlinux",
+	"../../../vmlinux",
+	"../../vmlinux",
+	NULL
+};
+
+static void kernel_usage_with_options(void)
+{
+	const char **k;
+	struct utsname uts;
+
+	fprintf(stderr, "Fatal: could not find default kernel image in:\n");
+	k = &default_kernels[0];
+	while (*k) {
+		fprintf(stderr, "\t%s\n", *k);
+		k++;
+	}
+
+	if (uname(&uts) < 0)
+		return;
+
+	k = &host_kernels[0];
+	while (*k) {
+		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
+			return;
+		fprintf(stderr, "\t%s\n", kernel);
+		k++;
+	}
+	fprintf(stderr, "\nPlease see '%s run --help' for more options.\n\n",
+		KVM_BINARY_NAME);
+}
+
+static u64 host_ram_size(void)
+{
+	long page_size;
+	long nr_pages;
+
+	nr_pages	= sysconf(_SC_PHYS_PAGES);
+	if (nr_pages < 0) {
+		pr_warning("sysconf(_SC_PHYS_PAGES) failed");
+		return 0;
+	}
+
+	page_size	= sysconf(_SC_PAGE_SIZE);
+	if (page_size < 0) {
+		pr_warning("sysconf(_SC_PAGE_SIZE) failed");
+		return 0;
+	}
+
+	return (nr_pages * page_size) >> MB_SHIFT;
+}
+
+/*
+ * If user didn't specify how much memory it wants to allocate for the guest,
+ * avoid filling the whole host RAM.
+ */
+#define RAM_SIZE_RATIO		0.8
+
+static u64 get_ram_size(int nr_cpus)
+{
+	u64 available;
+	u64 ram_size;
+
+	ram_size	= 64 * (nr_cpus + 3);
+
+	available	= host_ram_size() * RAM_SIZE_RATIO;
+	if (!available)
+		available = MIN_RAM_SIZE_MB;
+
+	if (ram_size > available)
+		ram_size	= available;
+
+	return ram_size;
+}
+
+static const char *find_kernel(void)
+{
+	const char **k;
+	struct stat st;
+	struct utsname uts;
+
+	k = &default_kernels[0];
+	while (*k) {
+		if (stat(*k, &st) < 0 || !S_ISREG(st.st_mode)) {
+			k++;
+			continue;
+		}
+		strncpy(kernel, *k, PATH_MAX);
+		return kernel;
+	}
+
+	if (uname(&uts) < 0)
+		return NULL;
+
+	k = &host_kernels[0];
+	while (*k) {
+		if (snprintf(kernel, PATH_MAX, "%s-%s", *k, uts.release) < 0)
+			return NULL;
+
+		if (stat(kernel, &st) < 0 || !S_ISREG(st.st_mode)) {
+			k++;
+			continue;
+		}
+		return kernel;
+
+	}
+	return NULL;
+}
+
+static const char *find_vmlinux(void)
+{
+	const char **vmlinux;
+
+	vmlinux = &default_vmlinux[0];
+	while (*vmlinux) {
+		struct stat st;
+
+		if (stat(*vmlinux, &st) < 0 || !S_ISREG(st.st_mode)) {
+			vmlinux++;
+			continue;
+		}
+		return *vmlinux;
+	}
+	return NULL;
+}
+
+void kvm_run_help(void)
+{
+	usage_with_options(run_usage, options);
+}
+
+static int kvm_custom_stage2(void)
+{
+	char tmp[PATH_MAX], dst[PATH_MAX], *src;
+	const char *rootfs = custom_rootfs_name;
+	int r;
+
+	src = realpath("guest/init_stage2", NULL);
+	if (src == NULL)
+		return -ENOMEM;
+
+	snprintf(tmp, PATH_MAX, "%s%s/virt/init_stage2", kvm__get_dir(), rootfs);
+	remove(tmp);
+
+	snprintf(dst, PATH_MAX, "/host/%s", src);
+	r = symlink(dst, tmp);
+	free(src);
+
+	return r;
+}
+
+static int kvm_run_set_sandbox(void)
+{
+	const char *guestfs_name = custom_rootfs_name;
+	char path[PATH_MAX], script[PATH_MAX], *tmp;
+
+	snprintf(path, PATH_MAX, "%s%s/virt/sandbox.sh", kvm__get_dir(), guestfs_name);
+
+	remove(path);
+
+	if (sandbox == NULL)
+		return 0;
+
+	tmp = realpath(sandbox, NULL);
+	if (tmp == NULL)
+		return -ENOMEM;
+
+	snprintf(script, PATH_MAX, "/host/%s", tmp);
+	free(tmp);
+
+	return symlink(script, path);
+}
+
+static void kvm_write_sandbox_cmd_exactly(int fd, const char *arg)
+{
+	const char *single_quote;
+
+	if (!*arg) { /* zero length string */
+		if (write(fd, "''", 2) <= 0)
+			die("Failed writing sandbox script");
+		return;
+	}
+
+	while (*arg) {
+		single_quote = strchrnul(arg, '\'');
+
+		/* write non-single-quote string as #('string') */
+		if (arg != single_quote) {
+			if (write(fd, "'", 1) <= 0 ||
+			    write(fd, arg, single_quote - arg) <= 0 ||
+			    write(fd, "'", 1) <= 0)
+				die("Failed writing sandbox script");
+		}
+
+		/* write single quote as #("'") */
+		if (*single_quote) {
+			if (write(fd, "\"'\"", 3) <= 0)
+				die("Failed writing sandbox script");
+		} else
+			break;
+
+		arg = single_quote + 1;
+	}
+}
+
+static void kvm_run_write_sandbox_cmd(const char **argv, int argc)
+{
+	const char script_hdr[] = "#! /bin/bash\n\n";
+	int fd;
+
+	remove(sandbox);
+
+	fd = open(sandbox, O_RDWR | O_CREAT, 0777);
+	if (fd < 0)
+		die("Failed creating sandbox script");
+
+	if (write(fd, script_hdr, sizeof(script_hdr) - 1) <= 0)
+		die("Failed writing sandbox script");
+
+	while (argc) {
+		kvm_write_sandbox_cmd_exactly(fd, argv[0]);
+		if (argc - 1)
+			if (write(fd, " ", 1) <= 0)
+				die("Failed writing sandbox script");
+		argv++;
+		argc--;
+	}
+	if (write(fd, "\n", 1) <= 0)
+		die("Failed writing sandbox script");
+
+	close(fd);
+}
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix)
+{
+	static char real_cmdline[2048], default_name[20];
+	struct framebuffer *fb = NULL;
+	unsigned int nr_online_cpus;
+	int exit_code = 0;
+	int max_cpus, recommended_cpus;
+	int i;
+	void *ret;
+
+	signal(SIGALRM, handle_sigalrm);
+	kvm_ipc__register_handler(KVM_IPC_DEBUG, handle_debug);
+	signal(SIGUSR1, handle_sigusr1);
+	kvm_ipc__register_handler(KVM_IPC_PAUSE, handle_pause);
+	kvm_ipc__register_handler(KVM_IPC_RESUME, handle_pause);
+	kvm_ipc__register_handler(KVM_IPC_STOP, handle_stop);
+	kvm_ipc__register_handler(KVM_IPC_VMSTATE, handle_vmstate);
+
+	nr_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+	while (argc != 0) {
+		argc = parse_options(argc, argv, options, run_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION |
+				PARSE_OPT_KEEP_DASHDASH);
+		if (argc != 0) {
+			/* Cusrom options, should have been handled elsewhere */
+			if (strcmp(argv[0], "--") == 0) {
+				if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
+					sandbox = DEFAULT_SANDBOX_FILENAME;
+					kvm_run_write_sandbox_cmd(argv+1, argc-1);
+					break;
+				}
+			}
+
+			if ((kvm_run_wrapper == KVM_RUN_DEFAULT && kernel_filename) ||
+				(kvm_run_wrapper == KVM_RUN_SANDBOX && sandbox)) {
+				fprintf(stderr, "Cannot handle parameter: "
+						"%s\n", argv[0]);
+				usage_with_options(run_usage, options);
+				return EINVAL;
+			}
+			if (kvm_run_wrapper == KVM_RUN_SANDBOX) {
+				/*
+				 * first unhandled parameter is treated as
+				 * sandbox command
+				 */
+				sandbox = DEFAULT_SANDBOX_FILENAME;
+				kvm_run_write_sandbox_cmd(argv, argc);
+			} else {
+				/*
+				 * first unhandled parameter is treated as a kernel
+				 * image
+				 */
+				kernel_filename = argv[0];
+			}
+			argv++;
+			argc--;
+		}
+
+	}
+
+	if (!kernel_filename)
+		kernel_filename = find_kernel();
+
+	if (!kernel_filename) {
+		kernel_usage_with_options();
+		return EINVAL;
+	}
+
+	vmlinux_filename = find_vmlinux();
+
+	if (nrcpus == 0)
+		nrcpus = nr_online_cpus;
+
+	if (!ram_size)
+		ram_size	= get_ram_size(nrcpus);
+
+	if (ram_size < MIN_RAM_SIZE_MB)
+		die("Not enough memory specified: %lluMB (min %lluMB)", ram_size, MIN_RAM_SIZE_MB);
+
+	if (ram_size > host_ram_size())
+		pr_warning("Guest memory size %lluMB exceeds host physical RAM size %lluMB", ram_size, host_ram_size());
+
+	ram_size <<= MB_SHIFT;
+
+	if (!dev)
+		dev = DEFAULT_KVM_DEV;
+
+	if (!console)
+		console = DEFAULT_CONSOLE;
+
+	if (!strncmp(console, "virtio", 6))
+		active_console  = CONSOLE_VIRTIO;
+	else if (!strncmp(console, "serial", 6))
+		active_console  = CONSOLE_8250;
+	else if (!strncmp(console, "hv", 2))
+		active_console = CONSOLE_HV;
+	else
+		pr_warning("No console!");
+
+	if (!host_ip)
+		host_ip = DEFAULT_HOST_ADDR;
+
+	if (!guest_ip)
+		guest_ip = DEFAULT_GUEST_ADDR;
+
+	if (!guest_mac)
+		guest_mac = DEFAULT_GUEST_MAC;
+
+	if (!host_mac)
+		host_mac = DEFAULT_HOST_MAC;
+
+	if (!script)
+		script = DEFAULT_SCRIPT;
+
+	symbol__init(vmlinux_filename);
+
+	term_init();
+
+	if (!guest_name) {
+		if (custom_rootfs) {
+			guest_name = custom_rootfs_name;
+		} else {
+			sprintf(default_name, "guest-%u", getpid());
+			guest_name = default_name;
+		}
+	}
+
+	kvm = kvm__init(dev, hugetlbfs_path, ram_size, guest_name);
+
+	kvm->single_step = single_step;
+
+	ioeventfd__init(kvm);
+
+	max_cpus = kvm__max_cpus(kvm);
+	recommended_cpus = kvm__recommended_cpus(kvm);
+
+	if (nrcpus > max_cpus) {
+		printf("  # Limit the number of CPUs to %d\n", max_cpus);
+		nrcpus = max_cpus;
+	} else if (nrcpus > recommended_cpus) {
+		printf("  # Warning: The maximum recommended amount of VCPUs"
+			" is %d\n", recommended_cpus);
+	}
+
+	kvm->nrcpus = nrcpus;
+
+	/* Alloc one pointer too many, so array ends up 0-terminated */
+	kvm_cpus = calloc(nrcpus + 1, sizeof(void *));
+	if (!kvm_cpus)
+		die("Couldn't allocate array for %d CPUs", nrcpus);
+
+	irq__init(kvm);
+
+	pci__init();
+
+	/*
+	 * vidmode should be either specified
+	 * either set by default
+	 */
+	if (vnc || sdl) {
+		if (vidmode == -1)
+			vidmode = 0x312;
+	} else
+		vidmode = 0;
+
+	memset(real_cmdline, 0, sizeof(real_cmdline));
+	kvm__arch_set_cmdline(real_cmdline, vnc || sdl);
+
+	if (strlen(real_cmdline) > 0)
+		strcat(real_cmdline, " ");
+
+	if (kernel_cmdline)
+		strlcat(real_cmdline, kernel_cmdline, sizeof(real_cmdline));
+
+	if (!using_rootfs && !image_filename[0] && !initrd_filename) {
+		char tmp[PATH_MAX];
+
+		kvm_setup_create_new(custom_rootfs_name);
+		kvm_setup_resolv(custom_rootfs_name);
+
+		snprintf(tmp, PATH_MAX, "%s%s", kvm__get_dir(), "default");
+		if (virtio_9p__register(kvm, tmp, "/dev/root") < 0)
+			die("Unable to initialize virtio 9p");
+		if (virtio_9p__register(kvm, "/", "hostfs") < 0)
+			die("Unable to initialize virtio 9p");
+		using_rootfs = custom_rootfs = 1;
+	}
+
+	if (using_rootfs) {
+		strcat(real_cmdline, " root=/dev/root rw rootflags=rw,trans=virtio,version=9p2000.L rootfstype=9p");
+		if (custom_rootfs) {
+			kvm_run_set_sandbox();
+
+			strcat(real_cmdline, " init=/virt/init");
+
+			if (!no_dhcp)
+				strcat(real_cmdline, "  ip=dhcp");
+			if (kvm_custom_stage2())
+				die("Failed linking stage 2 of init.");
+		}
+	} else if (!strstr(real_cmdline, "root=")) {
+		strlcat(real_cmdline, " root=/dev/vda rw ", sizeof(real_cmdline));
+	}
+
+	if (image_count) {
+		kvm->nr_disks = image_count;
+		kvm->disks    = disk_image__open_all(image_filename, readonly_image, image_count);
+		if (!kvm->disks)
+			die("Unable to load all disk images.");
+
+		virtio_blk__init_all(kvm);
+	}
+
+	printf("  # %s run -k %s -m %Lu -c %d --name %s\n", KVM_BINARY_NAME,
+		kernel_filename, ram_size / 1024 / 1024, nrcpus, guest_name);
+
+	if (!kvm__load_kernel(kvm, kernel_filename, initrd_filename,
+				real_cmdline, vidmode))
+		die("unable to load kernel %s", kernel_filename);
+
+	kvm->vmlinux		= vmlinux_filename;
+
+	ioport__setup_arch();
+
+	rtc__init();
+
+	serial8250__init(kvm);
+
+	if (active_console == CONSOLE_VIRTIO)
+		virtio_console__init(kvm);
+
+	if (virtio_rng)
+		virtio_rng__init(kvm);
+
+	if (balloon)
+		virtio_bln__init(kvm);
+
+	if (!network)
+		network = DEFAULT_NETWORK;
+
+	virtio_9p__init(kvm);
+
+	for (i = 0; i < num_net_devices; i++) {
+		net_params[i].kvm = kvm;
+		virtio_net__init(&net_params[i]);
+	}
+
+	if (num_net_devices == 0 && no_net == 0) {
+		struct virtio_net_params net_params;
+
+		net_params = (struct virtio_net_params) {
+			.guest_ip	= guest_ip,
+			.host_ip	= host_ip,
+			.kvm		= kvm,
+			.script		= script,
+			.mode		= NET_MODE_USER,
+		};
+		str_to_mac(guest_mac, net_params.guest_mac);
+		str_to_mac(host_mac, net_params.host_mac);
+
+		virtio_net__init(&net_params);
+	}
+
+	kvm__init_ram(kvm);
+
+#ifdef CONFIG_X86
+	kbd__init(kvm);
+#endif
+
+	pci_shmem__init(kvm);
+
+	if (vnc || sdl)
+		fb = vesa__init(kvm);
+
+	if (vnc) {
+		if (fb)
+			vnc__init(fb);
+	}
+
+	if (sdl) {
+		if (fb)
+			sdl__init(fb);
+	}
+
+	fb__start();
+
+	/* Device init all done; firmware init must
+	 * come after this (it may set up device trees etc.)
+	 */
+
+	kvm__start_timer(kvm);
+
+	exit_code = kvm__arch_setup_firmware(kvm);
+	if (exit_code)
+		goto err;
+
+	for (i = 0; i < nrcpus; i++) {
+		kvm_cpus[i] = kvm_cpu__init(kvm, i);
+		if (!kvm_cpus[i])
+			die("unable to initialize KVM VCPU");
+	}
+
+	thread_pool__init(nr_online_cpus);
+	ioeventfd__start();
+
+	for (i = 0; i < nrcpus; i++) {
+		if (pthread_create(&kvm_cpus[i]->thread, NULL, kvm_cpu_thread, kvm_cpus[i]) != 0)
+			die("unable to create KVM VCPU thread");
+	}
+
+	/* Only VCPU #0 is going to exit by itself when shutting down */
+	if (pthread_join(kvm_cpus[0]->thread, &ret) != 0)
+		exit_code = 1;
+
+	kvm_cpu__delete(kvm_cpus[0]);
+
+	for (i = 1; i < nrcpus; i++) {
+		if (kvm_cpus[i]->is_running) {
+			pthread_kill(kvm_cpus[i]->thread, SIGKVMEXIT);
+			if (pthread_join(kvm_cpus[i]->thread, &ret) != 0)
+				die("pthread_join");
+			kvm_cpu__delete(kvm_cpus[i]);
+		}
+		if (ret != NULL)
+			exit_code = 1;
+	}
+
+err:
+	compat__print_all_messages();
+
+	fb__stop();
+
+	virtio_blk__delete_all(kvm);
+	virtio_rng__delete_all(kvm);
+
+	disk_image__close_all(kvm->disks, image_count);
+	free(kvm_cpus);
+	kvm__delete(kvm);
+
+	if (!exit_code)
+		printf("\n  # KVM session ended normally.\n");
+
+	return exit_code;
+}
diff --git a/tools/kvm/builtin-sandbox.c b/tools/kvm/builtin-sandbox.c
new file mode 100644
index 0000000..433f536
--- /dev/null
+++ b/tools/kvm/builtin-sandbox.c
@@ -0,0 +1,9 @@
+#include "kvm/builtin-sandbox.h"
+#include "kvm/builtin-run.h"
+
+int kvm_cmd_sandbox(int argc, const char **argv, const char *prefix)
+{
+	kvm_run_set_wrapper_sandbox();
+
+	return kvm_cmd_run(argc, argv, prefix);
+}
diff --git a/tools/kvm/builtin-setup.c b/tools/kvm/builtin-setup.c
new file mode 100644
index 0000000..dd43fed
--- /dev/null
+++ b/tools/kvm/builtin-setup.c
@@ -0,0 +1,232 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-setup.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static const char *instance_name;
+
+static const char * const setup_usage[] = {
+	"lkvm setup [name]",
+	NULL
+};
+
+static const struct option setup_options[] = {
+	OPT_END()
+};
+
+static void parse_setup_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, setup_options, setup_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0 && instance_name)
+			kvm_setup_help();
+		else
+			instance_name = argv[0];
+		argv++;
+		argc--;
+	}
+}
+
+void kvm_setup_help(void)
+{
+	printf("\n%s setup creates a new rootfs under %s.\n"
+		"This can be used later by the '-d' parameter of '%s run'.\n",
+		kvm__get_dir(), KVM_BINARY_NAME, KVM_BINARY_NAME);
+	usage_with_options(setup_usage, setup_options);
+}
+
+static int copy_file(const char *from, const char *to)
+{
+	int in_fd, out_fd;
+	void *src, *dst;
+	struct stat st;
+	int err = -1;
+
+	in_fd = open(from, O_RDONLY);
+	if (in_fd < 0)
+		return err;
+
+	if (fstat(in_fd, &st) < 0)
+		goto error_close_in;
+
+	out_fd = open(to, O_RDWR | O_CREAT | O_TRUNC, st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+	if (out_fd < 0)
+		goto error_close_in;
+
+	src = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, in_fd, 0);
+	if (src == MAP_FAILED)
+		goto error_close_out;
+
+	if (ftruncate(out_fd, st.st_size) < 0)
+		goto error_munmap_src;
+
+	dst = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, out_fd, 0);
+	if (dst == MAP_FAILED)
+		goto error_munmap_src;
+
+	memcpy(dst, src, st.st_size);
+
+	if (fsync(out_fd) < 0)
+		goto error_munmap_dst;
+
+	err = 0;
+
+error_munmap_dst:
+	munmap(dst, st.st_size);
+error_munmap_src:
+	munmap(src, st.st_size);
+error_close_out:
+	close(out_fd);
+error_close_in:
+	close(in_fd);
+
+	return err;
+}
+
+static const char *guestfs_dirs[] = {
+	"/dev",
+	"/etc",
+	"/home",
+	"/host",
+	"/proc",
+	"/root",
+	"/sys",
+	"/tmp",
+	"/var",
+	"/var/lib",
+	"/virt",
+};
+
+static const char *guestfs_symlinks[] = {
+	"/bin",
+	"/lib",
+	"/lib64",
+	"/sbin",
+	"/usr",
+	"/etc/ld.so.conf",
+};
+
+static int copy_init(const char *guestfs_name)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, PATH_MAX, "%s%s/virt/init", kvm__get_dir(), guestfs_name);
+
+	return copy_file("guest/init", path);
+}
+
+static int copy_passwd(const char *guestfs_name)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, PATH_MAX, "%s%s/etc/passwd", kvm__get_dir(), guestfs_name);
+
+	return copy_file("guest/passwd", path);
+}
+
+static int make_guestfs_symlink(const char *guestfs_name, const char *path)
+{
+	char target[PATH_MAX];
+	char name[PATH_MAX];
+
+	snprintf(name, PATH_MAX, "%s%s%s", kvm__get_dir(), guestfs_name, path);
+
+	snprintf(target, PATH_MAX, "/host%s", path);
+
+	return symlink(target, name);
+}
+
+static int make_dir(const char *dir)
+{
+	char name[PATH_MAX];
+
+	snprintf(name, PATH_MAX, "%s%s", kvm__get_dir(), dir);
+
+	return mkdir(name, 0777);
+}
+
+static void make_guestfs_dir(const char *guestfs_name, const char *dir)
+{
+	char name[PATH_MAX];
+
+	snprintf(name, PATH_MAX, "%s%s", guestfs_name, dir);
+
+	make_dir(name);
+}
+
+void kvm_setup_resolv(const char *guestfs_name)
+{
+	char path[PATH_MAX];
+
+	snprintf(path, PATH_MAX, "%s%s/etc/resolv.conf", kvm__get_dir(), guestfs_name);
+
+	copy_file("/etc/resolv.conf", path);
+}
+
+static int do_setup(const char *guestfs_name)
+{
+	unsigned int i;
+	int ret;
+
+	ret = make_dir(guestfs_name);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(guestfs_dirs); i++)
+		make_guestfs_dir(guestfs_name, guestfs_dirs[i]);
+
+	for (i = 0; i < ARRAY_SIZE(guestfs_symlinks); i++) {
+		make_guestfs_symlink(guestfs_name, guestfs_symlinks[i]);
+	}
+
+	ret = copy_init(guestfs_name);
+	if (ret < 0)
+		return ret;
+
+	return copy_passwd(guestfs_name);
+}
+
+int kvm_setup_create_new(const char *guestfs_name)
+{
+	return do_setup(guestfs_name);
+}
+
+int kvm_cmd_setup(int argc, const char **argv, const char *prefix)
+{
+	int r;
+
+	parse_setup_options(argc, argv);
+
+	if (instance_name == NULL)
+		kvm_setup_help();
+
+	r = do_setup(instance_name);
+	if (r == 0)
+		printf("A new rootfs '%s' has been created in '%s%s'.\n\n"
+			"You can now start it by running the following command:\n\n"
+			"  %s run -d %s\n",
+			instance_name, kvm__get_dir(), instance_name,
+			KVM_BINARY_NAME,instance_name);
+	else
+		printf("Unable to create rootfs in %s%s: %s\n",
+			kvm__get_dir(), instance_name, strerror(errno));
+
+	return r;
+}
diff --git a/tools/kvm/builtin-stat.c b/tools/kvm/builtin-stat.c
new file mode 100644
index 0000000..ffd72e8
--- /dev/null
+++ b/tools/kvm/builtin-stat.c
@@ -0,0 +1,127 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-stat.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <sys/select.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include <linux/virtio_balloon.h>
+
+static bool mem;
+static bool all;
+static const char *instance_name;
+
+static const char * const stat_usage[] = {
+	"lkvm stat [command] [--all] [-n name]",
+	NULL
+};
+
+static const struct option stat_options[] = {
+	OPT_GROUP("Commands options:"),
+	OPT_BOOLEAN('m', "memory", &mem, "Display memory statistics"),
+	OPT_GROUP("Instance options:"),
+	OPT_BOOLEAN('a', "all", &all, "All instances"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_END()
+};
+
+static void parse_stat_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, stat_options, stat_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_stat_help();
+	}
+}
+
+void kvm_stat_help(void)
+{
+	usage_with_options(stat_usage, stat_options);
+}
+
+static int do_memstat(const char *name, int sock)
+{
+	struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
+	fd_set fdset;
+	struct timeval t = { .tv_sec = 1 };
+	int r;
+	u8 i;
+
+	FD_ZERO(&fdset);
+	FD_SET(sock, &fdset);
+	r = kvm_ipc__send(sock, KVM_IPC_STAT);
+	if (r < 0)
+		return r;
+
+	r = select(1, &fdset, NULL, NULL, &t);
+	if (r < 0) {
+		pr_err("Could not retrieve mem stats from %s", name);
+		return r;
+	}
+	r = read(sock, &stats, sizeof(stats));
+	if (r < 0)
+		return r;
+
+	printf("\n\n\t*** Guest memory statistics ***\n\n");
+	for (i = 0; i < VIRTIO_BALLOON_S_NR; i++) {
+		switch (stats[i].tag) {
+		case VIRTIO_BALLOON_S_SWAP_IN:
+			printf("The amount of memory that has been swapped in (in bytes):");
+			break;
+		case VIRTIO_BALLOON_S_SWAP_OUT:
+			printf("The amount of memory that has been swapped out to disk (in bytes):");
+			break;
+		case VIRTIO_BALLOON_S_MAJFLT:
+			printf("The number of major page faults that have occurred:");
+			break;
+		case VIRTIO_BALLOON_S_MINFLT:
+			printf("The number of minor page faults that have occurred:");
+			break;
+		case VIRTIO_BALLOON_S_MEMFREE:
+			printf("The amount of memory not being used for any purpose (in bytes):");
+			break;
+		case VIRTIO_BALLOON_S_MEMTOT:
+			printf("The total amount of memory available (in bytes):");
+			break;
+		}
+		printf("%llu\n", stats[i].val);
+	}
+	printf("\n");
+
+	return 0;
+}
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix)
+{
+	int instance;
+	int r = 0;
+
+	parse_stat_options(argc, argv);
+
+	if (!mem)
+		usage_with_options(stat_usage, stat_options);
+
+	if (mem && all)
+		return kvm__enumerate_instances(do_memstat);
+
+	if (instance_name == NULL)
+		kvm_stat_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	if (mem)
+		r = do_memstat(instance_name, instance);
+
+	close(instance);
+
+	return r;
+}
diff --git a/tools/kvm/builtin-stop.c b/tools/kvm/builtin-stop.c
new file mode 100644
index 0000000..6067630
--- /dev/null
+++ b/tools/kvm/builtin-stop.c
@@ -0,0 +1,70 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-stop.h>
+#include <kvm/kvm.h>
+#include <kvm/parse-options.h>
+#include <kvm/kvm-ipc.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static bool all;
+static const char *instance_name;
+
+static const char * const stop_usage[] = {
+	"lkvm stop [--all] [-n name]",
+	NULL
+};
+
+static const struct option stop_options[] = {
+	OPT_GROUP("General options:"),
+	OPT_BOOLEAN('a', "all", &all, "Stop all instances"),
+	OPT_STRING('n', "name", &instance_name, "name", "Instance name"),
+	OPT_END()
+};
+
+static void parse_stop_options(int argc, const char **argv)
+{
+	while (argc != 0) {
+		argc = parse_options(argc, argv, stop_options, stop_usage,
+				PARSE_OPT_STOP_AT_NON_OPTION);
+		if (argc != 0)
+			kvm_stop_help();
+	}
+}
+
+void kvm_stop_help(void)
+{
+	usage_with_options(stop_usage, stop_options);
+}
+
+static int do_stop(const char *name, int sock)
+{
+	return kvm_ipc__send(sock, KVM_IPC_STOP);
+}
+
+int kvm_cmd_stop(int argc, const char **argv, const char *prefix)
+{
+	int instance;
+	int r;
+
+	parse_stop_options(argc, argv);
+
+	if (all)
+		return kvm__enumerate_instances(do_stop);
+
+	if (instance_name == NULL)
+		kvm_stop_help();
+
+	instance = kvm__get_sock_by_instance(instance_name);
+
+	if (instance <= 0)
+		die("Failed locating instance");
+
+	r = do_stop(instance_name, instance);
+
+	close(instance);
+
+	return r;
+}
diff --git a/tools/kvm/builtin-version.c b/tools/kvm/builtin-version.c
new file mode 100644
index 0000000..b8bb859
--- /dev/null
+++ b/tools/kvm/builtin-version.c
@@ -0,0 +1,15 @@
+#include <kvm/util.h>
+#include <kvm/kvm-cmd.h>
+#include <kvm/builtin-version.h>
+#include <kvm/kvm.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+int kvm_cmd_version(int argc, const char **argv, const char *prefix)
+{
+	printf("kvm tool %s\n", KVMTOOLS_VERSION);
+
+	return 0;
+}
diff --git a/tools/kvm/code16gcc.h b/tools/kvm/code16gcc.h
new file mode 100644
index 0000000..d93e480
--- /dev/null
+++ b/tools/kvm/code16gcc.h
@@ -0,0 +1,15 @@
+/*
+ * code16gcc.h
+ *
+ * This file is -include'd when compiling 16-bit C code.
+ * Note: this asm() needs to be emitted before gcc emits any code.
+ * Depending on gcc version, this requires -fno-unit-at-a-time or
+ * -fno-toplevel-reorder.
+ *
+ * Hopefully gcc will eventually have a real -m16 option so we can
+ * drop this hack long term.
+ */
+
+#ifndef __ASSEMBLY__
+asm(".code16gcc");
+#endif
diff --git a/tools/kvm/command-list.txt b/tools/kvm/command-list.txt
new file mode 100644
index 0000000..d93597d
--- /dev/null
+++ b/tools/kvm/command-list.txt
@@ -0,0 +1,15 @@
+#
+# List of known perf commands.
+# command name			category [deprecated] [common]
+#
+lkvm-run			mainporcelain common
+lkvm-setup			mainporcelain common
+lkvm-pause			common
+lkvm-resume			common
+lkvm-version			common
+lkvm-list			common
+lkvm-debug			common
+lkvm-balloon			common
+lkvm-stop			common
+lkvm-stat			common
+lkvm-sandbox			common
diff --git a/tools/kvm/config/feature-tests.mak b/tools/kvm/config/feature-tests.mak
new file mode 100644
index 0000000..be9ebc0
--- /dev/null
+++ b/tools/kvm/config/feature-tests.mak
@@ -0,0 +1,168 @@
+define SOURCE_HELLO
+#include <stdio.h>
+int main(void)
+{
+	return puts(\"hi\");
+}
+endef
+
+ifndef NO_DWARF
+define SOURCE_DWARF
+#include <dwarf.h>
+#include <elfutils/libdw.h>
+#include <elfutils/version.h>
+#ifndef _ELFUTILS_PREREQ
+#error
+#endif
+
+int main(void)
+{
+	Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
+	return (long)dbg;
+}
+endef
+endif
+
+define SOURCE_LIBELF
+#include <libelf.h>
+
+int main(void)
+{
+	Elf *elf = elf_begin(0, ELF_C_READ, 0);
+	return (long)elf;
+}
+endef
+
+define SOURCE_GLIBC
+#include <gnu/libc-version.h>
+
+int main(void)
+{
+	const char *version = gnu_get_libc_version();
+	return (long)version;
+}
+endef
+
+define SOURCE_ELF_MMAP
+#include <libelf.h>
+int main(void)
+{
+	Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
+	return (long)elf;
+}
+endef
+
+ifndef NO_NEWT
+define SOURCE_NEWT
+#include <newt.h>
+
+int main(void)
+{
+	newtInit();
+	newtCls();
+	return newtFinished();
+}
+endef
+endif
+
+ifndef NO_LIBPERL
+define SOURCE_PERL_EMBED
+#include <EXTERN.h>
+#include <perl.h>
+
+int main(void)
+{
+perl_alloc();
+return 0;
+}
+endef
+endif
+
+ifndef NO_LIBPYTHON
+define SOURCE_PYTHON_VERSION
+#include <Python.h>
+#if PY_VERSION_HEX >= 0x03000000
+	#error
+#endif
+int main(void){}
+endef
+define SOURCE_PYTHON_EMBED
+#include <Python.h>
+int main(void)
+{
+	Py_Initialize();
+	return 0;
+}
+endef
+endif
+
+define SOURCE_BFD
+#include <bfd.h>
+
+int main(void)
+{
+	bfd_demangle(0, 0, 0);
+	return 0;
+}
+endef
+
+define SOURCE_CPLUS_DEMANGLE
+extern char *cplus_demangle(const char *, int);
+
+int main(void)
+{
+	cplus_demangle(0, 0);
+	return 0;
+}
+endef
+
+define SOURCE_STRLCPY
+#include <stdlib.h>
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+int main(void)
+{
+	strlcpy(NULL, NULL, 0);
+	return 0;
+}
+endef
+
+define SOURCE_VNCSERVER
+#include <rfb/rfb.h>
+
+int main(void)
+{
+	rfbIsActive((void *)0);
+	return 0;
+}
+endef
+
+define SOURCE_SDL
+#include <SDL/SDL.h>
+
+int main(void)
+{
+	SDL_Init(SDL_INIT_VIDEO);
+	return 0;
+}
+endef
+
+define SOURCE_ZLIB
+#include <zlib.h>
+
+int main(void)
+{
+	inflateInit2(NULL, 0);
+	return 0;
+}
+endef
+
+define SOURCE_AIO
+#include <libaio.h>
+
+int main(void)
+{
+	io_setup(0, NULL);
+	return 0;
+}
+endef
diff --git a/tools/kvm/config/utilities.mak b/tools/kvm/config/utilities.mak
new file mode 100644
index 0000000..8046182
--- /dev/null
+++ b/tools/kvm/config/utilities.mak
@@ -0,0 +1,188 @@
+# This allows us to work with the newline character:
+define newline
+
+
+endef
+newline := $(newline)
+
+# nl-escape
+#
+# Usage: escape = $(call nl-escape[,escape])
+#
+# This is used as the common way to specify
+# what should replace a newline when escaping
+# newlines; the default is a bizarre string.
+#
+nl-escape = $(or $(1),m822df3020w6a44id34bt574ctac44eb9f4n)
+
+# escape-nl
+#
+# Usage: escaped-text = $(call escape-nl,text[,escape])
+#
+# GNU make's $(shell ...) function converts to a
+# single space each newline character in the output
+# produced during the expansion; this may not be
+# desirable.
+#
+# The only solution is to change each newline into
+# something that won't be converted, so that the
+# information can be recovered later with
+# $(call unescape-nl...)
+#
+escape-nl = $(subst $(newline),$(call nl-escape,$(2)),$(1))
+
+# unescape-nl
+#
+# Usage: text = $(call unescape-nl,escaped-text[,escape])
+#
+# See escape-nl.
+#
+unescape-nl = $(subst $(call nl-escape,$(2)),$(newline),$(1))
+
+# shell-escape-nl
+#
+# Usage: $(shell some-command | $(call shell-escape-nl[,escape]))
+#
+# Use this to escape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as a string constant
+#       in an `awk' program that is delimited by shell
+#       single-quotes, so be wary of the characters
+#       that are chosen.
+#
+define shell-escape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "$(nl-escape)" $$0} END {printf t}'
+endef
+
+# shell-unescape-nl
+#
+# Usage: $(shell some-command | $(call shell-unescape-nl[,escape]))
+#
+# Use this to unescape newlines from within a shell call;
+# the default escape is a bizarre string.
+#
+# NOTE: The escape is used directly as an extended regular
+#       expression constant in an `awk' program that is
+#       delimited by shell single-quotes, so be wary
+#       of the characters that are chosen.
+#
+# (The bash shell has a bug where `{gsub(...),...}' is
+#  misinterpreted as a brace expansion; this can be
+#  overcome by putting a space between `{' and `gsub').
+#
+define shell-unescape-nl
+awk 'NR==1 {t=$$0} NR>1 {t=t "\n" $$0} END { gsub(/$(nl-escape)/,"\n",t); printf t }'
+endef
+
+# escape-for-shell-sq
+#
+# Usage: embeddable-text = $(call escape-for-shell-sq,text)
+#
+# This function produces text that is suitable for
+# embedding in a shell string that is delimited by
+# single-quotes.
+#
+escape-for-shell-sq =  $(subst ','\'',$(1))
+
+# shell-sq
+#
+# Usage: single-quoted-and-escaped-text = $(call shell-sq,text)
+#
+shell-sq = '$(escape-for-shell-sq)'
+
+# shell-wordify
+#
+# Usage: wordified-text = $(call shell-wordify,text)
+#
+# For instance:
+#
+#  |define text
+#  |hello
+#  |world
+#  |endef
+#  |
+#  |target:
+#  |	echo $(call shell-wordify,$(text))
+#
+# At least GNU make gets confused by expanding a newline
+# within the context of a command line of a makefile rule
+# (this is in constrast to a `$(shell ...)' function call,
+# which can handle it just fine).
+#
+# This function avoids the problem by producing a string
+# that works as a shell word, regardless of whether or
+# not it contains a newline.
+#
+# If the text to be wordified contains a newline, then
+# an intrictate shell command substitution is constructed
+# to render the text as a single line; when the shell
+# processes the resulting escaped text, it transforms
+# it into the original unescaped text.
+#
+# If the text does not contain a newline, then this function
+# produces the same results as the `$(shell-sq)' function.
+#
+shell-wordify = $(if $(findstring $(newline),$(1)),$(_sw-esc-nl),$(shell-sq))
+define _sw-esc-nl
+"$$(echo $(call escape-nl,$(shell-sq),$(2)) | $(call shell-unescape-nl,$(2)))"
+endef
+
+# is-absolute
+#
+# Usage: bool-value = $(call is-absolute,path)
+#
+is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y)
+
+# lookup
+#
+# Usage: absolute-executable-path-or-empty = $(call lookup,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+lookup = $(call unescape-nl,$(shell sh -c $(_l-sh)))
+_l-sh = $(call shell-sq,command -v $(shell-sq) | $(call shell-escape-nl,))
+
+# is-executable
+#
+# Usage: bool-value = $(call is-executable,path)
+#
+# (It's necessary to use `sh -c' because GNU make messes up by
+#  trying too hard and getting things wrong).
+#
+is-executable = $(call _is-executable-helper,$(shell-sq))
+_is-executable-helper = $(shell sh -c $(_is-executable-sh))
+_is-executable-sh = $(call shell-sq,test -f $(1) -a -x $(1) && echo y)
+
+# get-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable,path)
+#
+# The goal is to get an absolute path for an executable;
+# the `command -v' is defined by POSIX, but it's not
+# necessarily very portable, so it's only used if
+# relative path resolution is requested, as determined
+# by the presence of a leading `/'.
+#
+get-executable = $(if $(1),$(if $(is-absolute),$(_ge-abspath),$(lookup)))
+_ge-abspath = $(if $(is-executable),$(1))
+
+# get-supplied-or-default-executable
+#
+# Usage: absolute-executable-path-or-empty = $(call get-executable-or-default,variable,default)
+#
+define get-executable-or-default
+$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
+endef
+_ge_attempt = $(or $(get-executable),$(_gea_warn),$(call _gea_err,$(2)))
+_gea_warn = $(warning The path '$(1)' is not executable.)
+_gea_err  = $(if $(1),$(error Please set '$(1)' appropriately))
+
+# try-cc
+# Usage: option = $(call try-cc, source-to-build, cc-options)
+try-cc = $(shell sh -c						  \
+	'TMP="$(OUTPUT)$(TMPOUT).$$$$";				  \
+	 echo "$(1)" |						  \
+	 $(CC) -x c - $(2) -o "$$TMP" > /dev/null 2>&1 && echo y; \
+	 rm -f "$$TMP"')
diff --git a/tools/kvm/disk/blk.c b/tools/kvm/disk/blk.c
new file mode 100644
index 0000000..59294e8
--- /dev/null
+++ b/tools/kvm/disk/blk.c
@@ -0,0 +1,39 @@
+#include "kvm/disk-image.h"
+
+/*
+ * raw image and blk dev are similar, so reuse raw image ops.
+ */
+static struct disk_image_operations blk_dev_ops = {
+	.read_sector		= raw_image__read_sector,
+	.write_sector		= raw_image__write_sector,
+	.close			= raw_image__close,
+};
+
+struct disk_image *blkdev__probe(const char *filename, struct stat *st)
+{
+	u64 size;
+	int fd;
+
+	if (!S_ISBLK(st->st_mode))
+		return NULL;
+
+	/*
+	 * Be careful! We are opening host block device!
+	 * Open it readonly since we do not want to break user's data on disk.
+	 */
+	fd			= open(filename, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+
+	if (ioctl(fd, BLKGETSIZE64, &size) < 0) {
+		close(fd);
+		return NULL;
+	}
+
+	/*
+	 * FIXME: This will not work on 32-bit host because we can not
+	 * mmap large disk. There is not enough virtual address space
+	 * in 32-bit host. However, this works on 64-bit host.
+	 */
+	return disk_image__new(fd, size, &blk_dev_ops, DISK_IMAGE_MMAP);
+}
diff --git a/tools/kvm/disk/core.c b/tools/kvm/disk/core.c
new file mode 100644
index 0000000..3da0efe
--- /dev/null
+++ b/tools/kvm/disk/core.c
@@ -0,0 +1,242 @@
+#include "kvm/disk-image.h"
+#include "kvm/qcow.h"
+#include "kvm/virtio-blk.h"
+
+#include <sys/eventfd.h>
+#include <sys/poll.h>
+
+#define AIO_MAX 32
+
+int debug_iodelay;
+
+#ifdef CONFIG_HAS_AIO
+static void *disk_image__thread(void *param)
+{
+	struct disk_image *disk = param;
+	struct io_event event[AIO_MAX];
+	struct timespec notime = {0};
+	int nr, i;
+	u64 dummy;
+
+	while (read(disk->evt, &dummy, sizeof(dummy)) > 0) {
+		nr = io_getevents(disk->ctx, 1, ARRAY_SIZE(event), event, &notime);
+		for (i = 0; i < nr; i++)
+			disk->disk_req_cb(event[i].data, event[i].res);
+	}
+
+	return NULL;
+}
+#endif
+
+struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int use_mmap)
+{
+	struct disk_image *disk;
+
+	disk		= malloc(sizeof *disk);
+	if (!disk)
+		return NULL;
+
+	disk->fd	= fd;
+	disk->size	= size;
+	disk->ops	= ops;
+
+	if (use_mmap == DISK_IMAGE_MMAP) {
+		/*
+		 * The write to disk image will be discarded
+		 */
+		disk->priv = mmap(NULL, size, PROT_RW, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
+		if (disk->priv == MAP_FAILED) {
+			free(disk);
+			disk = NULL;
+		}
+	}
+
+#ifdef CONFIG_HAS_AIO
+	if (disk) {
+		pthread_t thread;
+
+		disk->evt = eventfd(0, 0);
+		io_setup(AIO_MAX, &disk->ctx);
+		if (pthread_create(&thread, NULL, disk_image__thread, disk) != 0)
+			die("Failed starting IO thread");
+	}
+#endif
+	return disk;
+}
+
+struct disk_image *disk_image__open(const char *filename, bool readonly)
+{
+	struct disk_image *disk;
+	struct stat st;
+	int fd;
+
+	if (stat(filename, &st) < 0)
+		return NULL;
+
+	/* blk device ?*/
+	disk		= blkdev__probe(filename, &st);
+	if (disk)
+		return disk;
+
+	fd		= open(filename, readonly ? O_RDONLY : O_RDWR);
+	if (fd < 0)
+		return NULL;
+
+	/* qcow image ?*/
+	disk		= qcow_probe(fd, true);
+	if (disk) {
+		pr_warning("Forcing read-only support for QCOW");
+		return disk;
+	}
+
+	/* raw image ?*/
+	disk		= raw_image__probe(fd, &st, readonly);
+	if (disk)
+		return disk;
+
+	if (close(fd) < 0)
+		pr_warning("close() failed");
+
+	return NULL;
+}
+
+struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count)
+{
+	struct disk_image **disks;
+	int i;
+
+	if (!count || count > MAX_DISK_IMAGES)
+		return NULL;
+
+	disks = calloc(count, sizeof(*disks));
+	if (!disks)
+		return NULL;
+
+	for (i = 0; i < count; i++) {
+		if (!filenames[i])
+			continue;
+
+		disks[i] = disk_image__open(filenames[i], readonly[i]);
+		if (!disks[i]) {
+			pr_err("Loading disk image '%s' failed", filenames[i]);
+			goto error;
+		}
+	}
+
+	return disks;
+error:
+	for (i = 0; i < count; i++)
+		disk_image__close(disks[i]);
+
+	free(disks);
+	return NULL;
+}
+
+int disk_image__flush(struct disk_image *disk)
+{
+	if (disk->ops->flush)
+		return disk->ops->flush(disk);
+
+	return fsync(disk->fd);
+}
+
+int disk_image__close(struct disk_image *disk)
+{
+	/* If there was no disk image then there's nothing to do: */
+	if (!disk)
+		return 0;
+
+	if (disk->ops->close)
+		return disk->ops->close(disk);
+
+	if (close(disk->fd) < 0)
+		pr_warning("close() failed");
+
+	free(disk);
+
+	return 0;
+}
+
+void disk_image__close_all(struct disk_image **disks, int count)
+{
+	while (count)
+		disk_image__close(disks[--count]);
+
+	free(disks);
+}
+
+/*
+ * Fill iov with disk data, starting from sector 'sector'.
+ * Return amount of bytes read.
+ */
+ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	ssize_t total = 0;
+
+	if (debug_iodelay)
+		msleep(debug_iodelay);
+
+	if (disk->ops->read_sector) {
+		total = disk->ops->read_sector(disk, sector, iov, iovcount, param);
+		if (total < 0) {
+			pr_info("disk_image__read error: total=%ld\n", (long)total);
+			return -1;
+		}
+	} else {
+		/* Do nothing */
+	}
+
+	if (!disk->async && disk->disk_req_cb)
+		disk->disk_req_cb(param, total);
+
+	return total;
+}
+
+/*
+ * Write iov to disk, starting from sector 'sector'.
+ * Return amount of bytes written.
+ */
+ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	ssize_t total = 0;
+
+	if (debug_iodelay)
+		msleep(debug_iodelay);
+
+	if (disk->ops->write_sector) {
+		/*
+		 * Try writev based operation first
+		 */
+
+		total = disk->ops->write_sector(disk, sector, iov, iovcount, param);
+		if (total < 0) {
+			pr_info("disk_image__write error: total=%ld\n", (long)total);
+			return -1;
+		}
+	} else {
+		/* Do nothing */
+	}
+
+	if (!disk->async && disk->disk_req_cb)
+		disk->disk_req_cb(param, total);
+
+	return total;
+}
+
+ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len)
+{
+	struct stat st;
+
+	if (fstat(disk->fd, &st) != 0)
+		return 0;
+
+	*len = snprintf(buffer, *len, "%llu%llu%llu", (u64)st.st_dev, (u64)st.st_rdev, (u64)st.st_ino);
+	return *len;
+}
+
+void disk_image__set_callback(struct disk_image *disk, void (*disk_req_cb)(void *param, long len))
+{
+	disk->disk_req_cb = disk_req_cb;
+}
diff --git a/tools/kvm/disk/qcow.c b/tools/kvm/disk/qcow.c
new file mode 100644
index 0000000..712f811
--- /dev/null
+++ b/tools/kvm/disk/qcow.c
@@ -0,0 +1,1529 @@
+#include "kvm/qcow.h"
+
+#include "kvm/disk-image.h"
+#include "kvm/read-write.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifdef CONFIG_HAS_ZLIB
+#include <zlib.h>
+#endif
+
+#include <linux/err.h>
+#include <linux/byteorder.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+static int update_cluster_refcount(struct qcow *q, u64 clust_idx, u16 append);
+static int qcow_write_refcount_table(struct qcow *q);
+static u64 qcow_alloc_clusters(struct qcow *q, u64 size, int update_ref);
+static void  qcow_free_clusters(struct qcow *q, u64 clust_start, u64 size);
+
+static inline int qcow_pwrite_sync(int fd,
+	void *buf, size_t count, off_t offset)
+{
+	if (pwrite_in_full(fd, buf, count, offset) < 0)
+		return -1;
+
+	return fdatasync(fd);
+}
+
+static int l2_table_insert(struct rb_root *root, struct qcow_l2_table *new)
+{
+	struct rb_node **link = &(root->rb_node), *parent = NULL;
+	u64 offset = new->offset;
+
+	/* search the tree */
+	while (*link) {
+		struct qcow_l2_table *t;
+
+		t = rb_entry(*link, struct qcow_l2_table, node);
+		if (!t)
+			goto error;
+
+		parent = *link;
+
+		if (t->offset > offset)
+			link = &(*link)->rb_left;
+		else if (t->offset < offset)
+			link = &(*link)->rb_right;
+		else
+			goto out;
+	}
+
+	/* add new node */
+	rb_link_node(&new->node, parent, link);
+	rb_insert_color(&new->node, root);
+out:
+	return 0;
+error:
+	return -1;
+}
+
+static struct qcow_l2_table *l2_table_lookup(struct rb_root *root, u64 offset)
+{
+	struct rb_node *link = root->rb_node;
+
+	while (link) {
+		struct qcow_l2_table *t;
+
+		t = rb_entry(link, struct qcow_l2_table, node);
+		if (!t)
+			goto out;
+
+		if (t->offset > offset)
+			link = link->rb_left;
+		else if (t->offset < offset)
+			link = link->rb_right;
+		else
+			return t;
+	}
+out:
+	return NULL;
+}
+
+static void l1_table_free_cache(struct qcow_l1_table *l1t)
+{
+	struct rb_root *r = &l1t->root;
+	struct list_head *pos, *n;
+	struct qcow_l2_table *t;
+
+	list_for_each_safe(pos, n, &l1t->lru_list) {
+		/* Remove cache table from the list and RB tree */
+		list_del(pos);
+		t = list_entry(pos, struct qcow_l2_table, list);
+		rb_erase(&t->node, r);
+
+		/* Free the cached node */
+		free(t);
+	}
+}
+
+static int qcow_l2_cache_write(struct qcow *q, struct qcow_l2_table *c)
+{
+	struct qcow_header *header = q->header;
+	u64 size;
+
+	if (!c->dirty)
+		return 0;
+
+	size = 1 << header->l2_bits;
+
+	if (qcow_pwrite_sync(q->fd, c->table,
+		size * sizeof(u64), c->offset) < 0)
+		return -1;
+
+	c->dirty = 0;
+
+	return 0;
+}
+
+static int cache_table(struct qcow *q, struct qcow_l2_table *c)
+{
+	struct qcow_l1_table *l1t = &q->table;
+	struct rb_root *r = &l1t->root;
+	struct qcow_l2_table *lru;
+
+	if (l1t->nr_cached == MAX_CACHE_NODES) {
+		/*
+		 * The node at the head of the list is least recently used
+		 * node. Remove it from the list and replaced with a new node.
+		 */
+		lru = list_first_entry(&l1t->lru_list, struct qcow_l2_table, list);
+
+		/* Remove the node from the cache */
+		rb_erase(&lru->node, r);
+		list_del_init(&lru->list);
+		l1t->nr_cached--;
+
+		/* Free the LRUed node */
+		free(lru);
+	}
+
+	/* Add new node in RB Tree: Helps in searching faster */
+	if (l2_table_insert(r, c) < 0)
+		goto error;
+
+	/* Add in LRU replacement list */
+	list_add_tail(&c->list, &l1t->lru_list);
+	l1t->nr_cached++;
+
+	return 0;
+error:
+	return -1;
+}
+
+static struct qcow_l2_table *l2_table_search(struct qcow *q, u64 offset)
+{
+	struct qcow_l1_table *l1t = &q->table;
+	struct qcow_l2_table *l2t;
+
+	l2t = l2_table_lookup(&l1t->root, offset);
+	if (!l2t)
+		return NULL;
+
+	/* Update the LRU state, by moving the searched node to list tail */
+	list_move_tail(&l2t->list, &l1t->lru_list);
+
+	return l2t;
+}
+
+/* Allocates a new node for caching L2 table */
+static struct qcow_l2_table *new_cache_table(struct qcow *q, u64 offset)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l2_table *c;
+	u64 l2t_sz;
+	u64 size;
+
+	l2t_sz = 1 << header->l2_bits;
+	size   = sizeof(*c) + l2t_sz * sizeof(u64);
+	c      = calloc(1, size);
+	if (!c)
+		goto out;
+
+	c->offset = offset;
+	RB_CLEAR_NODE(&c->node);
+	INIT_LIST_HEAD(&c->list);
+out:
+	return c;
+}
+
+static inline u64 get_l1_index(struct qcow *q, u64 offset)
+{
+	struct qcow_header *header = q->header;
+
+	return offset >> (header->l2_bits + header->cluster_bits);
+}
+
+static inline u64 get_l2_index(struct qcow *q, u64 offset)
+{
+	struct qcow_header *header = q->header;
+
+	return (offset >> (header->cluster_bits)) & ((1 << header->l2_bits)-1);
+}
+
+static inline u64 get_cluster_offset(struct qcow *q, u64 offset)
+{
+	struct qcow_header *header = q->header;
+
+	return offset & ((1 << header->cluster_bits)-1);
+}
+
+static struct qcow_l2_table *qcow_read_l2_table(struct qcow *q, u64 offset)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l2_table *l2t;
+	u64 size;
+
+	size = 1 << header->l2_bits;
+
+	/* search an entry for offset in cache */
+	l2t = l2_table_search(q, offset);
+	if (l2t)
+		return l2t;
+
+	/* allocate new node for caching l2 table */
+	l2t = new_cache_table(q, offset);
+	if (!l2t)
+		goto error;
+
+	/* table not cached: read from the disk */
+	if (pread_in_full(q->fd, l2t->table, size * sizeof(u64), offset) < 0)
+		goto error;
+
+	/* cache the table */
+	if (cache_table(q, l2t) < 0)
+		goto error;
+
+	return l2t;
+error:
+	free(l2t);
+	return NULL;
+}
+
+static int qcow_decompress_buffer(u8 *out_buf, int out_buf_size,
+	const u8 *buf, int buf_size)
+{
+#ifdef CONFIG_HAS_ZLIB
+	z_stream strm1, *strm = &strm1;
+	int ret, out_len;
+
+	memset(strm, 0, sizeof(*strm));
+
+	strm->next_in = (u8 *)buf;
+	strm->avail_in = buf_size;
+	strm->next_out = out_buf;
+	strm->avail_out = out_buf_size;
+
+	ret = inflateInit2(strm, -12);
+	if (ret != Z_OK)
+		return -1;
+
+	ret = inflate(strm, Z_FINISH);
+	out_len = strm->next_out - out_buf;
+	if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
+		out_len != out_buf_size) {
+		inflateEnd(strm);
+		return -1;
+	}
+
+	inflateEnd(strm);
+	return 0;
+#else
+	return -1;
+#endif
+}
+
+static ssize_t qcow1_read_cluster(struct qcow *q, u64 offset,
+	void *dst, u32 dst_len)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l1_table *l1t = &q->table;
+	struct qcow_l2_table *l2t;
+	u64 clust_offset;
+	u64 clust_start;
+	u64 l2t_offset;
+	size_t length;
+	u64 l2t_size;
+	u64 l1_idx;
+	u64 l2_idx;
+	int coffset;
+	int csize;
+
+	l1_idx = get_l1_index(q, offset);
+	if (l1_idx >= l1t->table_size)
+		return -1;
+
+	clust_offset = get_cluster_offset(q, offset);
+	if (clust_offset >= q->cluster_size)
+		return -1;
+
+	length = q->cluster_size - clust_offset;
+	if (length > dst_len)
+		length = dst_len;
+
+	mutex_lock(&q->mutex);
+
+	l2t_offset = be64_to_cpu(l1t->l1_table[l1_idx]);
+	if (!l2t_offset)
+		goto zero_cluster;
+
+	l2t_size = 1 << header->l2_bits;
+
+	/* read and cache level 2 table */
+	l2t = qcow_read_l2_table(q, l2t_offset);
+	if (!l2t)
+		goto out_error;
+
+	l2_idx = get_l2_index(q, offset);
+	if (l2_idx >= l2t_size)
+		goto out_error;
+
+	clust_start = be64_to_cpu(l2t->table[l2_idx]);
+	if (clust_start & QCOW1_OFLAG_COMPRESSED) {
+		coffset = clust_start & q->cluster_offset_mask;
+		csize = clust_start >> (63 - q->header->cluster_bits);
+		csize &= (q->cluster_size - 1);
+
+		if (pread_in_full(q->fd, q->cluster_data, csize,
+				  coffset) < 0)
+			goto out_error;
+
+		if (qcow_decompress_buffer(q->cluster_cache, q->cluster_size,
+					q->cluster_data, csize) < 0)
+			goto out_error;
+
+		memcpy(dst, q->cluster_cache + clust_offset, length);
+		mutex_unlock(&q->mutex);
+	} else {
+		if (!clust_start)
+			goto zero_cluster;
+
+		mutex_unlock(&q->mutex);
+
+		if (pread_in_full(q->fd, dst, length,
+				  clust_start + clust_offset) < 0)
+			return -1;
+	}
+
+	return length;
+
+zero_cluster:
+	mutex_unlock(&q->mutex);
+	memset(dst, 0, length);
+	return length;
+
+out_error:
+	mutex_unlock(&q->mutex);
+	length = -1;
+	return -1;
+}
+
+static ssize_t qcow2_read_cluster(struct qcow *q, u64 offset,
+	void *dst, u32 dst_len)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l1_table *l1t = &q->table;
+	struct qcow_l2_table *l2t;
+	u64 clust_offset;
+	u64 clust_start;
+	u64 l2t_offset;
+	size_t length;
+	u64 l2t_size;
+	u64 l1_idx;
+	u64 l2_idx;
+	int coffset;
+	int sector_offset;
+	int nb_csectors;
+	int csize;
+
+	l1_idx = get_l1_index(q, offset);
+	if (l1_idx >= l1t->table_size)
+		return -1;
+
+	clust_offset = get_cluster_offset(q, offset);
+	if (clust_offset >= q->cluster_size)
+		return -1;
+
+	length = q->cluster_size - clust_offset;
+	if (length > dst_len)
+		length = dst_len;
+
+	mutex_lock(&q->mutex);
+
+	l2t_offset = be64_to_cpu(l1t->l1_table[l1_idx]);
+
+	l2t_offset &= ~QCOW2_OFLAG_COPIED;
+	if (!l2t_offset)
+		goto zero_cluster;
+
+	l2t_size = 1 << header->l2_bits;
+
+	/* read and cache level 2 table */
+	l2t = qcow_read_l2_table(q, l2t_offset);
+	if (!l2t)
+		goto out_error;
+
+	l2_idx = get_l2_index(q, offset);
+	if (l2_idx >= l2t_size)
+		goto out_error;
+
+	clust_start = be64_to_cpu(l2t->table[l2_idx]);
+	if (clust_start & QCOW2_OFLAG_COMPRESSED) {
+		coffset = clust_start & q->cluster_offset_mask;
+		nb_csectors = ((clust_start >> q->csize_shift)
+			& q->csize_mask) + 1;
+		sector_offset = coffset & (SECTOR_SIZE - 1);
+		csize = nb_csectors * SECTOR_SIZE - sector_offset;
+
+		if (pread_in_full(q->fd, q->cluster_data,
+				  nb_csectors * SECTOR_SIZE,
+				  coffset & ~(SECTOR_SIZE - 1)) < 0) {
+			goto out_error;
+		}
+
+		if (qcow_decompress_buffer(q->cluster_cache, q->cluster_size,
+					q->cluster_data + sector_offset,
+					csize) < 0) {
+			goto out_error;
+		}
+
+		memcpy(dst, q->cluster_cache + clust_offset, length);
+		mutex_unlock(&q->mutex);
+	} else {
+		clust_start &= QCOW2_OFFSET_MASK;
+		if (!clust_start)
+			goto zero_cluster;
+
+		mutex_unlock(&q->mutex);
+
+		if (pread_in_full(q->fd, dst, length,
+				  clust_start + clust_offset) < 0)
+			return -1;
+	}
+
+	return length;
+
+zero_cluster:
+	mutex_unlock(&q->mutex);
+	memset(dst, 0, length);
+	return length;
+
+out_error:
+	mutex_unlock(&q->mutex);
+	length = -1;
+	return -1;
+}
+
+static ssize_t qcow_read_sector_single(struct disk_image *disk, u64 sector,
+	void *dst, u32 dst_len)
+{
+	struct qcow *q = disk->priv;
+	struct qcow_header *header = q->header;
+	u32 nr_read;
+	u64 offset;
+	char *buf;
+	u32 nr;
+
+	buf = dst;
+	nr_read = 0;
+
+	while (nr_read < dst_len) {
+		offset = sector << SECTOR_SHIFT;
+		if (offset >= header->size)
+			return -1;
+
+		if (q->version == QCOW1_VERSION)
+			nr = qcow1_read_cluster(q, offset, buf,
+				dst_len - nr_read);
+		else
+			nr = qcow2_read_cluster(q, offset, buf,
+				dst_len - nr_read);
+
+		if (nr <= 0)
+			return -1;
+
+		nr_read	+= nr;
+		buf	+= nr;
+		sector	+= (nr >> SECTOR_SHIFT);
+	}
+
+	return dst_len;
+}
+
+static ssize_t qcow_read_sector(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param)
+{
+	ssize_t nr, total = 0;
+
+	while (iovcount--) {
+		nr = qcow_read_sector_single(disk, sector, iov->iov_base, iov->iov_len);
+		if (nr != (ssize_t)iov->iov_len) {
+			pr_info("qcow_read_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
+			return -1;
+		}
+
+		sector += iov->iov_len >> SECTOR_SHIFT;
+		total += nr;
+		iov++;
+	}
+
+	return total;
+}
+
+static void refcount_table_free_cache(struct qcow_refcount_table *rft)
+{
+	struct rb_root *r = &rft->root;
+	struct list_head *pos, *n;
+	struct qcow_refcount_block *t;
+
+	list_for_each_safe(pos, n, &rft->lru_list) {
+		list_del(pos);
+		t = list_entry(pos, struct qcow_refcount_block, list);
+		rb_erase(&t->node, r);
+
+		free(t);
+	}
+}
+
+static int refcount_block_insert(struct rb_root *root, struct qcow_refcount_block *new)
+{
+	struct rb_node **link = &(root->rb_node), *parent = NULL;
+	u64 offset = new->offset;
+
+	/* search the tree */
+	while (*link) {
+		struct qcow_refcount_block *t;
+
+		t = rb_entry(*link, struct qcow_refcount_block, node);
+		if (!t)
+			goto error;
+
+		parent = *link;
+
+		if (t->offset > offset)
+			link = &(*link)->rb_left;
+		else if (t->offset < offset)
+			link = &(*link)->rb_right;
+		else
+			goto out;
+	}
+
+	/* add new node */
+	rb_link_node(&new->node, parent, link);
+	rb_insert_color(&new->node, root);
+out:
+	return 0;
+error:
+	return -1;
+}
+
+static int write_refcount_block(struct qcow *q, struct qcow_refcount_block *rfb)
+{
+	if (!rfb->dirty)
+		return 0;
+
+	if (qcow_pwrite_sync(q->fd, rfb->entries,
+		rfb->size * sizeof(u16), rfb->offset) < 0)
+		return -1;
+
+	rfb->dirty = 0;
+
+	return 0;
+}
+
+static int cache_refcount_block(struct qcow *q, struct qcow_refcount_block *c)
+{
+	struct qcow_refcount_table *rft = &q->refcount_table;
+	struct rb_root *r = &rft->root;
+	struct qcow_refcount_block *lru;
+
+	if (rft->nr_cached == MAX_CACHE_NODES) {
+		lru = list_first_entry(&rft->lru_list, struct qcow_refcount_block, list);
+
+		rb_erase(&lru->node, r);
+		list_del_init(&lru->list);
+		rft->nr_cached--;
+
+		free(lru);
+	}
+
+	if (refcount_block_insert(r, c) < 0)
+		goto error;
+
+	list_add_tail(&c->list, &rft->lru_list);
+	rft->nr_cached++;
+
+	return 0;
+error:
+	return -1;
+}
+
+static struct qcow_refcount_block *new_refcount_block(struct qcow *q, u64 rfb_offset)
+{
+	struct qcow_refcount_block *rfb;
+
+	rfb = malloc(sizeof *rfb + q->cluster_size);
+	if (!rfb)
+		return NULL;
+
+	rfb->offset = rfb_offset;
+	rfb->size = q->cluster_size / sizeof(u16);
+	RB_CLEAR_NODE(&rfb->node);
+	INIT_LIST_HEAD(&rfb->list);
+
+	return rfb;
+}
+
+static struct qcow_refcount_block *refcount_block_lookup(struct rb_root *root, u64 offset)
+{
+	struct rb_node *link = root->rb_node;
+
+	while (link) {
+		struct qcow_refcount_block *t;
+
+		t = rb_entry(link, struct qcow_refcount_block, node);
+		if (!t)
+			goto out;
+
+		if (t->offset > offset)
+			link = link->rb_left;
+		else if (t->offset < offset)
+			link = link->rb_right;
+		else
+			return t;
+	}
+out:
+	return NULL;
+}
+
+static struct qcow_refcount_block *refcount_block_search(struct qcow *q, u64 offset)
+{
+	struct qcow_refcount_table *rft = &q->refcount_table;
+	struct qcow_refcount_block *rfb;
+
+	rfb = refcount_block_lookup(&rft->root, offset);
+	if (!rfb)
+		return NULL;
+
+	/* Update the LRU state, by moving the searched node to list tail */
+	list_move_tail(&rfb->list, &rft->lru_list);
+
+	return rfb;
+}
+
+static struct qcow_refcount_block *qcow_grow_refcount_block(struct qcow *q,
+	u64 clust_idx)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_refcount_table *rft = &q->refcount_table;
+	struct qcow_refcount_block *rfb;
+	u64 new_block_offset;
+	u64 rft_idx;
+
+	rft_idx = clust_idx >> (header->cluster_bits -
+		QCOW_REFCOUNT_BLOCK_SHIFT);
+
+	if (rft_idx >= rft->rf_size) {
+		pr_warning("Don't support grow refcount block table");
+		return NULL;
+	}
+
+	new_block_offset = qcow_alloc_clusters(q, q->cluster_size, 0);
+	if (new_block_offset < 0)
+		return NULL;
+
+	rfb = new_refcount_block(q, new_block_offset);
+	if (!rfb)
+		return NULL;
+
+	memset(rfb->entries, 0x00, q->cluster_size);
+	rfb->dirty = 1;
+
+	/* write refcount block */
+	if (write_refcount_block(q, rfb) < 0)
+		goto free_rfb;
+
+	if (cache_refcount_block(q, rfb) < 0)
+		goto free_rfb;
+
+	rft->rf_table[rft_idx] = cpu_to_be64(new_block_offset);
+	if (update_cluster_refcount(q, new_block_offset >>
+		    header->cluster_bits, 1) < 0)
+		goto recover_rft;
+
+	if (qcow_write_refcount_table(q) < 0)
+		goto recover_rft;
+
+	return rfb;
+
+recover_rft:
+	rft->rf_table[rft_idx] = 0;
+free_rfb:
+	free(rfb);
+	return NULL;
+}
+
+static struct qcow_refcount_block *qcow_read_refcount_block(struct qcow *q, u64 clust_idx)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_refcount_table *rft = &q->refcount_table;
+	struct qcow_refcount_block *rfb;
+	u64 rfb_offset;
+	u64 rft_idx;
+
+	rft_idx = clust_idx >> (header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT);
+	if (rft_idx >= rft->rf_size)
+		return ERR_PTR(-ENOSPC);
+
+	rfb_offset = be64_to_cpu(rft->rf_table[rft_idx]);
+	if (!rfb_offset)
+		return ERR_PTR(-ENOSPC);
+
+	rfb = refcount_block_search(q, rfb_offset);
+	if (rfb)
+		return rfb;
+
+	rfb = new_refcount_block(q, rfb_offset);
+	if (!rfb)
+		return NULL;
+
+	if (pread_in_full(q->fd, rfb->entries, rfb->size * sizeof(u16), rfb_offset) < 0)
+		goto error_free_rfb;
+
+	if (cache_refcount_block(q, rfb) < 0)
+		goto error_free_rfb;
+
+	return rfb;
+
+error_free_rfb:
+	free(rfb);
+
+	return NULL;
+}
+
+static u16 qcow_get_refcount(struct qcow *q, u64 clust_idx)
+{
+	struct qcow_refcount_block *rfb = NULL;
+	struct qcow_header *header = q->header;
+	u64 rfb_idx;
+
+	rfb = qcow_read_refcount_block(q, clust_idx);
+	if (PTR_ERR(rfb) == -ENOSPC)
+		return 0;
+	else if (IS_ERR_OR_NULL(rfb)) {
+		pr_warning("Error while reading refcount table");
+		return -1;
+	}
+
+	rfb_idx = clust_idx & (((1ULL <<
+		(header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT)) - 1));
+
+	if (rfb_idx >= rfb->size) {
+		pr_warning("L1: refcount block index out of bounds");
+		return -1;
+	}
+
+	return be16_to_cpu(rfb->entries[rfb_idx]);
+}
+
+static int update_cluster_refcount(struct qcow *q, u64 clust_idx, u16 append)
+{
+	struct qcow_refcount_block *rfb = NULL;
+	struct qcow_header *header = q->header;
+	u16 refcount;
+	u64 rfb_idx;
+
+	rfb = qcow_read_refcount_block(q, clust_idx);
+	if (PTR_ERR(rfb) == -ENOSPC) {
+		rfb = qcow_grow_refcount_block(q, clust_idx);
+		if (!rfb) {
+			pr_warning("error while growing refcount table");
+			return -1;
+		}
+	} else if (IS_ERR_OR_NULL(rfb)) {
+		pr_warning("error while reading refcount table");
+		return -1;
+	}
+
+	rfb_idx = clust_idx & (((1ULL <<
+		(header->cluster_bits - QCOW_REFCOUNT_BLOCK_SHIFT)) - 1));
+	if (rfb_idx >= rfb->size) {
+		pr_warning("refcount block index out of bounds");
+		return -1;
+	}
+
+	refcount = be16_to_cpu(rfb->entries[rfb_idx]) + append;
+	rfb->entries[rfb_idx] = cpu_to_be16(refcount);
+	rfb->dirty = 1;
+
+	/* write refcount block */
+	if (write_refcount_block(q, rfb) < 0) {
+		pr_warning("refcount block index out of bounds");
+		return -1;
+	}
+
+	/* update free_clust_idx since refcount becomes zero */
+	if (!refcount && clust_idx < q->free_clust_idx)
+		q->free_clust_idx = clust_idx;
+
+	return 0;
+}
+
+static void  qcow_free_clusters(struct qcow *q, u64 clust_start, u64 size)
+{
+	struct qcow_header *header = q->header;
+	u64 start, end, offset;
+
+	start = clust_start & ~(q->cluster_size - 1);
+	end = (clust_start + size - 1) & ~(q->cluster_size - 1);
+	for (offset = start; offset <= end; offset += q->cluster_size)
+		update_cluster_refcount(q, offset >> header->cluster_bits, -1);
+}
+
+/*
+ * Allocate clusters according to the size. Find a postion that
+ * can satisfy the size. free_clust_idx is initialized to zero and
+ * Record last position.
+ */
+static u64 qcow_alloc_clusters(struct qcow *q, u64 size, int update_ref)
+{
+	struct qcow_header *header = q->header;
+	u16 clust_refcount;
+	u32 clust_idx = 0, i;
+	u64 clust_num;
+
+	clust_num = (size + (q->cluster_size - 1)) >> header->cluster_bits;
+
+again:
+	for (i = 0; i < clust_num; i++) {
+		clust_idx = q->free_clust_idx++;
+		clust_refcount = qcow_get_refcount(q, clust_idx);
+		if (clust_refcount < 0)
+			return -1;
+		else if (clust_refcount > 0)
+			goto again;
+	}
+
+	clust_idx++;
+
+	if (update_ref)
+		for (i = 0; i < clust_num; i++)
+			if (update_cluster_refcount(q,
+				clust_idx - clust_num + i, 1))
+				return -1;
+
+	return (clust_idx - clust_num) << header->cluster_bits;
+}
+
+static int qcow_write_l1_table(struct qcow *q)
+{
+	struct qcow_l1_table *l1t = &q->table;
+	struct qcow_header *header = q->header;
+
+	if (qcow_pwrite_sync(q->fd, l1t->l1_table,
+		l1t->table_size * sizeof(u64),
+		header->l1_table_offset) < 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Get l2 table. If the table has been copied, read table directly.
+ * If the table exists, allocate a new cluster and copy the table
+ * to the new cluster.
+ */
+static int get_cluster_table(struct qcow *q, u64 offset,
+	struct qcow_l2_table **result_l2t, u64 *result_l2_index)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l1_table *l1t = &q->table;
+	struct qcow_l2_table *l2t;
+	u64 l1t_idx;
+	u64 l2t_offset;
+	u64 l2t_idx;
+	u64 l2t_size;
+	u64 l2t_new_offset;
+
+	l2t_size = 1 << header->l2_bits;
+
+	l1t_idx = get_l1_index(q, offset);
+	if (l1t_idx >= l1t->table_size)
+		return -1;
+
+	l2t_idx = get_l2_index(q, offset);
+	if (l2t_idx >= l2t_size)
+		return -1;
+
+	l2t_offset = be64_to_cpu(l1t->l1_table[l1t_idx]);
+	if (l2t_offset & QCOW2_OFLAG_COPIED) {
+		l2t_offset &= ~QCOW2_OFLAG_COPIED;
+		l2t = qcow_read_l2_table(q, l2t_offset);
+		if (!l2t)
+			goto error;
+	} else {
+		l2t_new_offset = qcow_alloc_clusters(q,
+			l2t_size*sizeof(u64), 1);
+
+		if (l2t_new_offset < 0)
+			goto error;
+
+		l2t = new_cache_table(q, l2t_new_offset);
+		if (!l2t)
+			goto free_cluster;
+
+		if (l2t_offset) {
+			l2t = qcow_read_l2_table(q, l2t_offset);
+			if (!l2t)
+				goto free_cache;
+		} else
+			memset(l2t->table, 0x00, l2t_size * sizeof(u64));
+
+		/* write l2 table */
+		l2t->dirty = 1;
+		if (qcow_l2_cache_write(q, l2t) < 0)
+			goto free_cache;
+
+		/* cache l2 table */
+		if (cache_table(q, l2t))
+			goto free_cache;
+
+		/* update the l1 talble */
+		l1t->l1_table[l1t_idx] = cpu_to_be64(l2t_new_offset
+			| QCOW2_OFLAG_COPIED);
+		if (qcow_write_l1_table(q)) {
+			pr_warning("Update l1 table error");
+			goto free_cache;
+		}
+
+		/* free old cluster */
+		qcow_free_clusters(q, l2t_offset, q->cluster_size);
+	}
+
+	*result_l2t = l2t;
+	*result_l2_index = l2t_idx;
+
+	return 0;
+
+free_cache:
+	free(l2t);
+
+free_cluster:
+	qcow_free_clusters(q, l2t_new_offset, q->cluster_size);
+
+error:
+	return -1;
+}
+
+/*
+ * If the cluster has been copied, write data directly. If not,
+ * read the original data and write it to the new cluster with
+ * modification.
+ */
+static ssize_t qcow_write_cluster(struct qcow *q, u64 offset,
+		void *buf, u32 src_len)
+{
+	struct qcow_l2_table *l2t;
+	u64 clust_new_start;
+	u64 clust_start;
+	u64 clust_flags;
+	u64 clust_off;
+	u64 l2t_idx;
+	u64 len;
+
+	l2t = NULL;
+
+	clust_off = get_cluster_offset(q, offset);
+	if (clust_off >= q->cluster_size)
+		return -1;
+
+	len = q->cluster_size - clust_off;
+	if (len > src_len)
+		len = src_len;
+
+	mutex_lock(&q->mutex);
+
+	if (get_cluster_table(q, offset, &l2t, &l2t_idx)) {
+		pr_warning("Get l2 table error");
+		goto error;
+	}
+
+	clust_start = be64_to_cpu(l2t->table[l2t_idx]);
+	clust_flags = clust_start & QCOW2_OFLAGS_MASK;
+
+	clust_start &= QCOW2_OFFSET_MASK;
+	if (!(clust_flags & QCOW2_OFLAG_COPIED)) {
+		clust_new_start	= qcow_alloc_clusters(q, q->cluster_size, 1);
+		if (clust_new_start < 0) {
+			pr_warning("Cluster alloc error");
+			goto error;
+		}
+
+		offset &= ~(q->cluster_size - 1);
+
+		/* if clust_start is not zero, read the original data*/
+		if (clust_start) {
+			mutex_unlock(&q->mutex);
+			if (qcow2_read_cluster(q, offset, q->copy_buff,
+				q->cluster_size) < 0) {
+				pr_warning("Read copy cluster error");
+				qcow_free_clusters(q, clust_new_start,
+					q->cluster_size);
+				return -1;
+			}
+			mutex_lock(&q->mutex);
+		} else
+			memset(q->copy_buff, 0x00, q->cluster_size);
+
+		memcpy(q->copy_buff + clust_off, buf, len);
+
+		 /* Write actual data */
+		if (pwrite_in_full(q->fd, q->copy_buff, q->cluster_size,
+			clust_new_start) < 0)
+			goto free_cluster;
+
+		/* update l2 table*/
+		l2t->table[l2t_idx] = cpu_to_be64(clust_new_start
+			| QCOW2_OFLAG_COPIED);
+		l2t->dirty = 1;
+
+		if (qcow_l2_cache_write(q, l2t))
+			goto free_cluster;
+
+		/* free old cluster*/
+		if (clust_flags & QCOW2_OFLAG_COMPRESSED) {
+			int size;
+			size = ((clust_start >> q->csize_shift) &
+				q->csize_mask) + 1;
+			size *= 512;
+			clust_start &= q->cluster_offset_mask;
+			clust_start &= ~511;
+
+			qcow_free_clusters(q, clust_start, size);
+		} else if (clust_start)
+			qcow_free_clusters(q, clust_start, q->cluster_size);
+
+	} else {
+		/* Write actual data */
+		if (pwrite_in_full(q->fd, buf, len,
+			clust_start + clust_off) < 0)
+			goto error;
+	}
+	mutex_unlock(&q->mutex);
+	return len;
+
+free_cluster:
+	qcow_free_clusters(q, clust_new_start, q->cluster_size);
+
+error:
+	mutex_unlock(&q->mutex);
+	return -1;
+}
+
+static ssize_t qcow_write_sector_single(struct disk_image *disk, u64 sector, void *src, u32 src_len)
+{
+	struct qcow *q = disk->priv;
+	struct qcow_header *header = q->header;
+	u32 nr_written;
+	char *buf;
+	u64 offset;
+	ssize_t nr;
+
+	buf		= src;
+	nr_written	= 0;
+	offset		= sector << SECTOR_SHIFT;
+
+	while (nr_written < src_len) {
+		if (offset >= header->size)
+			return -1;
+
+		nr = qcow_write_cluster(q, offset, buf, src_len - nr_written);
+		if (nr < 0)
+			return -1;
+
+		nr_written	+= nr;
+		buf		+= nr;
+		offset		+= nr;
+	}
+
+	return nr_written;
+}
+
+static ssize_t qcow_write_sector(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param)
+{
+	ssize_t nr, total = 0;
+
+	while (iovcount--) {
+		nr = qcow_write_sector_single(disk, sector, iov->iov_base, iov->iov_len);
+		if (nr != (ssize_t)iov->iov_len) {
+			pr_info("qcow_write_sector error: nr=%ld iov_len=%ld\n", (long)nr, (long)iov->iov_len);
+			return -1;
+		}
+
+		sector	+= iov->iov_len >> SECTOR_SHIFT;
+		iov++;
+		total	+= nr;
+	}
+
+	return total;
+}
+
+static int qcow_disk_flush(struct disk_image *disk)
+{
+	struct qcow *q = disk->priv;
+	struct qcow_refcount_table *rft;
+	struct list_head *pos, *n;
+	struct qcow_l1_table *l1t;
+
+	l1t = &q->table;
+	rft = &q->refcount_table;
+
+	mutex_lock(&q->mutex);
+
+	list_for_each_safe(pos, n, &rft->lru_list) {
+		struct qcow_refcount_block *c = list_entry(pos, struct qcow_refcount_block, list);
+
+		if (write_refcount_block(q, c) < 0)
+			goto error_unlock;
+	}
+
+	list_for_each_safe(pos, n, &l1t->lru_list) {
+		struct qcow_l2_table *c = list_entry(pos, struct qcow_l2_table, list);
+
+		if (qcow_l2_cache_write(q, c) < 0)
+			goto error_unlock;
+	}
+
+	if (qcow_write_l1_table < 0)
+		goto error_unlock;
+
+	mutex_unlock(&q->mutex);
+
+	return fsync(disk->fd);
+
+error_unlock:
+	mutex_unlock(&q->mutex);
+	return -1;
+}
+
+static int qcow_disk_close(struct disk_image *disk)
+{
+	struct qcow *q;
+
+	if (!disk)
+		return 0;
+
+	q = disk->priv;
+
+	refcount_table_free_cache(&q->refcount_table);
+	l1_table_free_cache(&q->table);
+	free(q->copy_buff);
+	free(q->cluster_data);
+	free(q->cluster_cache);
+	free(q->refcount_table.rf_table);
+	free(q->table.l1_table);
+	free(q->header);
+	free(q);
+
+	return 0;
+}
+
+static struct disk_image_operations qcow_disk_readonly_ops = {
+	.read_sector		= qcow_read_sector,
+	.close			= qcow_disk_close,
+};
+
+static struct disk_image_operations qcow_disk_ops = {
+	.read_sector		= qcow_read_sector,
+	.write_sector		= qcow_write_sector,
+	.flush			= qcow_disk_flush,
+	.close			= qcow_disk_close,
+};
+
+static int qcow_read_refcount_table(struct qcow *q)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_refcount_table *rft = &q->refcount_table;
+
+	rft->rf_size = (header->refcount_table_size * q->cluster_size)
+		/ sizeof(u64);
+
+	rft->rf_table = calloc(rft->rf_size, sizeof(u64));
+	if (!rft->rf_table)
+		return -1;
+
+	rft->root = RB_ROOT;
+	INIT_LIST_HEAD(&rft->lru_list);
+
+	return pread_in_full(q->fd, rft->rf_table, sizeof(u64) * rft->rf_size, header->refcount_table_offset);
+}
+
+static int qcow_write_refcount_table(struct qcow *q)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_refcount_table *rft = &q->refcount_table;
+
+	return qcow_pwrite_sync(q->fd, rft->rf_table,
+		rft->rf_size * sizeof(u64), header->refcount_table_offset);
+}
+
+static int qcow_read_l1_table(struct qcow *q)
+{
+	struct qcow_header *header = q->header;
+	struct qcow_l1_table *table = &q->table;
+
+	table->table_size	= header->l1_size;
+
+	table->l1_table	= calloc(table->table_size, sizeof(u64));
+	if (!table->l1_table)
+		return -1;
+
+	return pread_in_full(q->fd, table->l1_table, sizeof(u64) * table->table_size, header->l1_table_offset);
+}
+
+static void *qcow2_read_header(int fd)
+{
+	struct qcow2_header_disk f_header;
+	struct qcow_header *header;
+
+	header = malloc(sizeof(struct qcow_header));
+	if (!header)
+		return NULL;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0) {
+		free(header);
+		return NULL;
+	}
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+	be64_to_cpus(&f_header.backing_file_offset);
+	be32_to_cpus(&f_header.backing_file_size);
+	be32_to_cpus(&f_header.cluster_bits);
+	be64_to_cpus(&f_header.size);
+	be32_to_cpus(&f_header.crypt_method);
+	be32_to_cpus(&f_header.l1_size);
+	be64_to_cpus(&f_header.l1_table_offset);
+	be64_to_cpus(&f_header.refcount_table_offset);
+	be32_to_cpus(&f_header.refcount_table_clusters);
+	be32_to_cpus(&f_header.nb_snapshots);
+	be64_to_cpus(&f_header.snapshots_offset);
+
+	*header		= (struct qcow_header) {
+		.size			= f_header.size,
+		.l1_table_offset	= f_header.l1_table_offset,
+		.l1_size		= f_header.l1_size,
+		.cluster_bits		= f_header.cluster_bits,
+		.l2_bits		= f_header.cluster_bits - 3,
+		.refcount_table_offset	= f_header.refcount_table_offset,
+		.refcount_table_size	= f_header.refcount_table_clusters,
+	};
+
+	return header;
+}
+
+static struct disk_image *qcow2_probe(int fd, bool readonly)
+{
+	struct disk_image *disk_image;
+	struct qcow_l1_table *l1t;
+	struct qcow_header *h;
+	struct qcow *q;
+
+	q = calloc(1, sizeof(struct qcow));
+	if (!q)
+		return NULL;
+
+	mutex_init(&q->mutex);
+	q->fd = fd;
+
+	l1t = &q->table;
+
+	l1t->root = RB_ROOT;
+	INIT_LIST_HEAD(&l1t->lru_list);
+
+	h = q->header = qcow2_read_header(fd);
+	if (!h)
+		goto free_qcow;
+
+	q->version = QCOW2_VERSION;
+	q->csize_shift = (62 - (q->header->cluster_bits - 8));
+	q->csize_mask = (1 << (q->header->cluster_bits - 8)) - 1;
+	q->cluster_offset_mask = (1LL << q->csize_shift) - 1;
+	q->cluster_size = 1 << q->header->cluster_bits;
+
+	q->copy_buff = malloc(q->cluster_size);
+	if (!q->copy_buff) {
+		pr_warning("copy buff malloc error");
+		goto free_header;
+	}
+
+	q->cluster_data = malloc(q->cluster_size);
+	if (!q->cluster_data) {
+		pr_warning("cluster data malloc error");
+		goto free_copy_buff;
+	}
+
+	q->cluster_cache = malloc(q->cluster_size);
+	if (!q->cluster_cache) {
+		pr_warning("cluster cache malloc error");
+		goto free_cluster_data;
+	}
+
+	if (qcow_read_l1_table(q) < 0)
+		goto free_cluster_cache;
+
+	if (qcow_read_refcount_table(q) < 0)
+		goto free_l1_table;
+
+	/*
+	 * Do not use mmap use read/write instead
+	 */
+	if (readonly)
+		disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_REGULAR);
+	else
+		disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_REGULAR);
+
+	if (!disk_image)
+		goto free_refcount_table;
+
+	disk_image->async = 0;
+	disk_image->priv = q;
+
+	return disk_image;
+
+free_refcount_table:
+	if (q->refcount_table.rf_table)
+		free(q->refcount_table.rf_table);
+free_l1_table:
+	if (q->table.l1_table)
+		free(q->table.l1_table);
+free_cluster_cache:
+	if (q->cluster_cache)
+		free(q->cluster_cache);
+free_cluster_data:
+	if (q->cluster_data)
+		free(q->cluster_data);
+free_copy_buff:
+	if (q->copy_buff)
+		free(q->copy_buff);
+free_header:
+	if (q->header)
+		free(q->header);
+free_qcow:
+	if (q)
+		free(q);
+
+	return NULL;
+}
+
+static bool qcow2_check_image(int fd)
+{
+	struct qcow2_header_disk f_header;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow2_header_disk), 0) < 0)
+		return false;
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+
+	if (f_header.magic != QCOW_MAGIC)
+		return false;
+
+	if (f_header.version != QCOW2_VERSION)
+		return false;
+
+	return true;
+}
+
+static void *qcow1_read_header(int fd)
+{
+	struct qcow1_header_disk f_header;
+	struct qcow_header *header;
+
+	header = malloc(sizeof(struct qcow_header));
+	if (!header)
+		return NULL;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0) {
+		free(header);
+		return NULL;
+	}
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+	be64_to_cpus(&f_header.backing_file_offset);
+	be32_to_cpus(&f_header.backing_file_size);
+	be32_to_cpus(&f_header.mtime);
+	be64_to_cpus(&f_header.size);
+	be32_to_cpus(&f_header.crypt_method);
+	be64_to_cpus(&f_header.l1_table_offset);
+
+	*header		= (struct qcow_header) {
+		.size			= f_header.size,
+		.l1_table_offset	= f_header.l1_table_offset,
+		.l1_size		= f_header.size / ((1 << f_header.l2_bits) * (1 << f_header.cluster_bits)),
+		.cluster_bits		= f_header.cluster_bits,
+		.l2_bits		= f_header.l2_bits,
+	};
+
+	return header;
+}
+
+static struct disk_image *qcow1_probe(int fd, bool readonly)
+{
+	struct disk_image *disk_image;
+	struct qcow_l1_table *l1t;
+	struct qcow_header *h;
+	struct qcow *q;
+
+	q = calloc(1, sizeof(struct qcow));
+	if (!q)
+		return NULL;
+
+	mutex_init(&q->mutex);
+	q->fd = fd;
+
+	l1t = &q->table;
+
+	l1t->root = RB_ROOT;
+	INIT_LIST_HEAD(&l1t->lru_list);
+
+	h = q->header = qcow1_read_header(fd);
+	if (!h)
+		goto free_qcow;
+
+	q->version = QCOW1_VERSION;
+	q->cluster_size = 1 << q->header->cluster_bits;
+	q->cluster_offset_mask = (1LL << (63 - q->header->cluster_bits)) - 1;
+	q->free_clust_idx = 0;
+
+	q->cluster_data = malloc(q->cluster_size);
+	if (!q->cluster_data) {
+		pr_warning("cluster data malloc error");
+		goto free_header;
+	}
+
+	q->cluster_cache = malloc(q->cluster_size);
+	if (!q->cluster_cache) {
+		pr_warning("cluster cache malloc error");
+		goto free_cluster_data;
+	}
+
+	if (qcow_read_l1_table(q) < 0)
+		goto free_cluster_cache;
+
+	/*
+	 * Do not use mmap use read/write instead
+	 */
+	if (readonly)
+		disk_image = disk_image__new(fd, h->size, &qcow_disk_readonly_ops, DISK_IMAGE_REGULAR);
+	else
+		disk_image = disk_image__new(fd, h->size, &qcow_disk_ops, DISK_IMAGE_REGULAR);
+
+	if (!disk_image)
+		goto free_l1_table;
+
+	disk_image->async = 1;
+	disk_image->priv = q;
+
+	return disk_image;
+
+free_l1_table:
+	if (q->table.l1_table)
+		free(q->table.l1_table);
+free_cluster_cache:
+	if (q->cluster_cache)
+		free(q->cluster_cache);
+free_cluster_data:
+	if (q->cluster_data)
+		free(q->cluster_data);
+free_header:
+	if (q->header)
+		free(q->header);
+free_qcow:
+	if (q)
+		free(q);
+
+	return NULL;
+}
+
+static bool qcow1_check_image(int fd)
+{
+	struct qcow1_header_disk f_header;
+
+	if (pread_in_full(fd, &f_header, sizeof(struct qcow1_header_disk), 0) < 0)
+		return false;
+
+	be32_to_cpus(&f_header.magic);
+	be32_to_cpus(&f_header.version);
+
+	if (f_header.magic != QCOW_MAGIC)
+		return false;
+
+	if (f_header.version != QCOW1_VERSION)
+		return false;
+
+	return true;
+}
+
+struct disk_image *qcow_probe(int fd, bool readonly)
+{
+	if (qcow1_check_image(fd))
+		return qcow1_probe(fd, readonly);
+
+	if (qcow2_check_image(fd))
+		return qcow2_probe(fd, readonly);
+
+	return NULL;
+}
diff --git a/tools/kvm/disk/raw.c b/tools/kvm/disk/raw.c
new file mode 100644
index 0000000..caa023c
--- /dev/null
+++ b/tools/kvm/disk/raw.c
@@ -0,0 +1,140 @@
+#include "kvm/disk-image.h"
+
+#ifdef CONFIG_HAS_AIO
+#include <libaio.h>
+#endif
+
+ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	u64 offset = sector << SECTOR_SHIFT;
+
+#ifdef CONFIG_HAS_AIO
+	struct iocb iocb;
+
+	return aio_preadv(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
+				disk->evt, param);
+#else
+	return preadv_in_full(disk->fd, iov, iovcount, offset);
+#endif
+}
+
+ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	u64 offset = sector << SECTOR_SHIFT;
+
+#ifdef CONFIG_HAS_AIO
+	struct iocb iocb;
+
+	return aio_pwritev(disk->ctx, &iocb, disk->fd, iov, iovcount, offset,
+				disk->evt, param);
+#else
+	return pwritev_in_full(disk->fd, iov, iovcount, offset);
+#endif
+}
+
+ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	u64 offset = sector << SECTOR_SHIFT;
+	ssize_t total = 0;
+
+	while (iovcount--) {
+		memcpy(iov->iov_base, disk->priv + offset, iov->iov_len);
+
+		sector	+= iov->iov_len >> SECTOR_SHIFT;
+		offset	+= iov->iov_len;
+		total	+= iov->iov_len;
+		iov++;
+	}
+
+	return total;
+}
+
+ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param)
+{
+	u64 offset = sector << SECTOR_SHIFT;
+	ssize_t total = 0;
+
+	while (iovcount--) {
+		memcpy(disk->priv + offset, iov->iov_base, iov->iov_len);
+
+		sector	+= iov->iov_len >> SECTOR_SHIFT;
+		offset	+= iov->iov_len;
+		total	+= iov->iov_len;
+		iov++;
+	}
+
+	return total;
+}
+
+int raw_image__close(struct disk_image *disk)
+{
+	int ret = 0;
+
+	if (disk->priv != MAP_FAILED)
+		ret = munmap(disk->priv, disk->size);
+
+	close(disk->evt);
+
+#ifdef CONFIG_HAS_VIRTIO
+	io_destroy(disk->ctx);
+#endif
+
+	return ret;
+}
+
+/*
+ * multiple buffer based disk image operations
+ */
+static struct disk_image_operations raw_image_regular_ops = {
+	.read_sector	= raw_image__read_sector,
+	.write_sector	= raw_image__write_sector,
+};
+
+struct disk_image_operations ro_ops = {
+	.read_sector	= raw_image__read_sector_mmap,
+	.write_sector	= raw_image__write_sector_mmap,
+	.close		= raw_image__close,
+};
+
+struct disk_image_operations ro_ops_nowrite = {
+	.read_sector	= raw_image__read_sector,
+};
+
+struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly)
+{
+	struct disk_image *disk;
+
+	if (readonly) {
+		/*
+		 * Use mmap's MAP_PRIVATE to implement non-persistent write
+		 * FIXME: This does not work on 32-bit host.
+		 */
+		struct disk_image *disk;
+
+		disk = disk_image__new(fd, st->st_size, &ro_ops, DISK_IMAGE_MMAP);
+		if (disk == NULL) {
+
+			disk = disk_image__new(fd, st->st_size, &ro_ops_nowrite, DISK_IMAGE_REGULAR);
+#ifdef CONFIG_HAS_AIO
+			if (disk)
+				disk->async = 1;
+#endif
+		}
+
+		return disk;
+	} else {
+		/*
+		 * Use read/write instead of mmap
+		 */
+		disk = disk_image__new(fd, st->st_size, &raw_image_regular_ops, DISK_IMAGE_REGULAR);
+#ifdef CONFIG_HAS_AIO
+		if (disk)
+			disk->async = 1;
+#endif
+		return disk;
+	}
+}
diff --git a/tools/kvm/framebuffer.c b/tools/kvm/framebuffer.c
new file mode 100644
index 0000000..b6eb1ac
--- /dev/null
+++ b/tools/kvm/framebuffer.c
@@ -0,0 +1,68 @@
+#include "kvm/framebuffer.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+static LIST_HEAD(framebuffers);
+
+struct framebuffer *fb__register(struct framebuffer *fb)
+{
+	INIT_LIST_HEAD(&fb->node);
+	list_add(&fb->node, &framebuffers);
+
+	return fb;
+}
+
+int fb__attach(struct framebuffer *fb, struct fb_target_operations *ops)
+{
+	if (fb->nr_targets >= FB_MAX_TARGETS)
+		return -1;
+
+	fb->targets[fb->nr_targets++] = ops;
+
+	return 0;
+}
+
+static int start_targets(struct framebuffer *fb)
+{
+	unsigned long i;
+
+	for (i = 0; i < fb->nr_targets; i++) {
+		struct fb_target_operations *ops = fb->targets[i];
+		int err = 0;
+
+		if (ops->start)
+			err = ops->start(fb);
+
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+int fb__start(void)
+{
+	struct framebuffer *fb;
+
+	list_for_each_entry(fb, &framebuffers, node) {
+		int err;
+
+		err = start_targets(fb);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+void fb__stop(void)
+{
+	struct framebuffer *fb;
+
+	list_for_each_entry(fb, &framebuffers, node) {
+		munmap(fb->mem, fb->mem_size);
+	}
+}
diff --git a/tools/kvm/guest/init.c b/tools/kvm/guest/init.c
new file mode 100644
index 0000000..032a261
--- /dev/null
+++ b/tools/kvm/guest/init.c
@@ -0,0 +1,38 @@
+/*
+ * This is a simple init for shared rootfs guests. This part should be limited
+ * to doing mounts and running stage 2 of the init process.
+ */
+#include <sys/mount.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+static int run_process(char *filename)
+{
+	char *new_argv[] = { filename, NULL };
+	char *new_env[] = { "TERM=linux", NULL };
+
+	return execve(filename, new_argv, new_env);
+}
+
+static void do_mounts(void)
+{
+	mount("hostfs", "/host", "9p", MS_RDONLY, "trans=virtio,version=9p2000.L");
+	mount("", "/sys", "sysfs", 0, NULL);
+	mount("proc", "/proc", "proc", 0, NULL);
+	mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
+}
+
+int main(int argc, char *argv[])
+{
+	puts("Mounting...");
+
+	do_mounts();
+
+	run_process("/virt/init_stage2");
+
+	printf("Init failed: %s\n", strerror(errno));
+
+	return 0;
+}
diff --git a/tools/kvm/guest/init_stage2.c b/tools/kvm/guest/init_stage2.c
new file mode 100644
index 0000000..5f93894
--- /dev/null
+++ b/tools/kvm/guest/init_stage2.c
@@ -0,0 +1,55 @@
+/*
+ * This is a stage 2 of the init. This part should do all the heavy
+ * lifting such as setting up the console and calling /bin/sh.
+ */
+#include <sys/mount.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <linux/reboot.h>
+
+static int run_process(char *filename)
+{
+	char *new_argv[] = { filename, NULL };
+	char *new_env[] = { "TERM=linux", NULL };
+
+	return execve(filename, new_argv, new_env);
+}
+
+static int run_process_sandbox(char *filename)
+{
+	char *new_argv[] = { filename, "/virt/sandbox.sh", NULL };
+	char *new_env[] = { "TERM=linux", NULL };
+
+	return execve(filename, new_argv, new_env);
+}
+
+int main(int argc, char *argv[])
+{
+	pid_t child;
+	int status;
+
+	/* get session leader */
+	setsid();
+
+	/* set controlling terminal */
+	ioctl(0, TIOCSCTTY, 1);
+
+	child = fork();
+	if (child < 0) {
+		printf("Fatal: fork() failed with %d\n", child);
+		return 0;
+	} else if (child == 0) {
+		if (access("/virt/sandbox.sh", R_OK) == 0)
+			run_process_sandbox("/bin/sh");
+		else
+			run_process("/bin/sh");
+	} else {
+		waitpid(child, &status, 0);
+	}
+
+	reboot(LINUX_REBOOT_CMD_RESTART);
+
+	return 0;
+}
diff --git a/tools/kvm/guest/passwd b/tools/kvm/guest/passwd
new file mode 100644
index 0000000..eb85a55
--- /dev/null
+++ b/tools/kvm/guest/passwd
@@ -0,0 +1 @@
+root:x:0:0:root:/root:/bin/sh
diff --git a/tools/kvm/guest_compat.c b/tools/kvm/guest_compat.c
new file mode 100644
index 0000000..43b9035
--- /dev/null
+++ b/tools/kvm/guest_compat.c
@@ -0,0 +1,99 @@
+#include "kvm/guest_compat.h"
+
+#include "kvm/mutex.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+struct compat_message {
+	int id;
+	char *title;
+	char *desc;
+
+	struct list_head list;
+};
+
+static int id;
+static DEFINE_MUTEX(compat_mtx);
+static LIST_HEAD(messages);
+
+static void compat__free(struct compat_message *msg)
+{
+	free(msg->title);
+	free(msg->desc);
+	free(msg);
+}
+
+int compat__add_message(const char *title, const char *desc)
+{
+	struct compat_message *msg;
+	int msg_id;
+
+	msg = malloc(sizeof(*msg));
+	if (msg == NULL)
+		goto cleanup;
+
+	msg->title = strdup(title);
+	msg->desc = strdup(desc);
+
+	if (msg->title == NULL || msg->desc == NULL)
+		goto cleanup;
+
+	mutex_lock(&compat_mtx);
+
+	msg->id = msg_id = id++;
+	list_add_tail(&msg->list, &messages);
+
+	mutex_unlock(&compat_mtx);
+
+	return msg_id;
+
+cleanup:
+	if (msg)
+		compat__free(msg);
+
+	return -ENOMEM;
+}
+
+int compat__remove_message(int id)
+{
+	struct compat_message *pos, *n;
+
+	mutex_lock(&compat_mtx);
+
+	list_for_each_entry_safe(pos, n, &messages, list) {
+		if (pos->id == id) {
+			list_del(&pos->list);
+			compat__free(pos);
+
+			mutex_unlock(&compat_mtx);
+
+			return 0;
+		}
+	}
+
+	mutex_unlock(&compat_mtx);
+
+	return -ENOENT;
+}
+
+int compat__print_all_messages(void)
+{
+	mutex_lock(&compat_mtx);
+
+	while (!list_empty(&messages)) {
+		struct compat_message *msg;
+
+		msg = list_first_entry(&messages, struct compat_message, list);
+
+		printf("\n\n*** Compatibility Warning ***\n\n\t%s\n\n%s\n",
+			msg->title, msg->desc);
+
+		list_del(&msg->list);
+		compat__free(msg);
+	}
+
+	mutex_unlock(&compat_mtx);
+
+	return 0;
+}
diff --git a/tools/kvm/hw/i8042.c b/tools/kvm/hw/i8042.c
new file mode 100644
index 0000000..3a36425
--- /dev/null
+++ b/tools/kvm/hw/i8042.c
@@ -0,0 +1,348 @@
+#include "kvm/read-write.h"
+#include "kvm/ioport.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+#include "kvm/i8042.h"
+#include "kvm/kvm-cpu.h"
+
+#include <stdint.h>
+
+/*
+ * IRQs
+ */
+#define KBD_IRQ			1
+#define AUX_IRQ			12
+
+/*
+ * Registers
+ */
+#define I8042_DATA_REG		0x60
+#define I8042_COMMAND_REG	0x64
+
+/*
+ * Commands
+ */
+#define I8042_CMD_CTL_RCTR	0x20
+#define I8042_CMD_CTL_WCTR	0x60
+#define I8042_CMD_AUX_LOOP	0xD3
+#define I8042_CMD_AUX_SEND	0xD4
+#define I8042_CMD_AUX_TEST	0xA9
+#define I8042_CMD_AUX_DISABLE	0xA7
+#define I8042_CMD_AUX_ENABLE	0xA8
+#define I8042_CMD_SYSTEM_RESET	0xFE
+
+#define RESPONSE_ACK		0xFA
+
+#define MODE_DISABLE_AUX	0x20
+
+#define AUX_ENABLE_REPORTING	0x20
+#define AUX_SCALING_FLAG	0x10
+#define AUX_DEFAULT_RESOLUTION	0x2
+#define AUX_DEFAULT_SAMPLE	100
+
+/*
+ * Status register bits
+ */
+#define I8042_STR_AUXDATA	0x20
+#define I8042_STR_KEYLOCK	0x10
+#define I8042_STR_CMDDAT	0x08
+#define I8042_STR_MUXERR	0x04
+#define I8042_STR_OBF		0x01
+
+#define KBD_MODE_KBD_INT	0x01
+#define KBD_MODE_SYS		0x02
+
+#define QUEUE_SIZE		128
+
+/*
+ * This represents the current state of the PS/2 keyboard system,
+ * including the AUX device (the mouse)
+ */
+struct kbd_state {
+	struct kvm		*kvm;
+
+	char			kq[QUEUE_SIZE];	/* Keyboard queue */
+	int			kread, kwrite;	/* Indexes into the queue */
+	int			kcount;		/* number of elements in queue */
+
+	char			mq[QUEUE_SIZE];
+	int			mread, mwrite;
+	int			mcount;
+
+	u8			mstatus;	/* Mouse status byte */
+	u8			mres;		/* Current mouse resolution */
+	u8			msample;	/* Current mouse samples/second */
+
+	u8			mode;		/* i8042 mode register */
+	u8			status;		/* i8042 status register */
+	/*
+	 * Some commands (on port 0x64) have arguments;
+	 * we store the command here while we wait for the argument
+	 */
+	u32			write_cmd;
+};
+
+static struct kbd_state		state;
+
+/*
+ * If there are packets to be read, set the appropriate IRQs high
+ */
+static void kbd_update_irq(void)
+{
+	u8 klevel = 0;
+	u8 mlevel = 0;
+
+	/* First, clear the kbd and aux output buffer full bits */
+	state.status &= ~(I8042_STR_OBF | I8042_STR_AUXDATA);
+
+	if (state.kcount > 0) {
+		state.status |= I8042_STR_OBF;
+		klevel = 1;
+	}
+
+	/* Keyboard has higher priority than mouse */
+	if (klevel == 0 && state.mcount != 0) {
+		state.status |= I8042_STR_OBF | I8042_STR_AUXDATA;
+		mlevel = 1;
+	}
+
+	kvm__irq_line(state.kvm, KBD_IRQ, klevel);
+	kvm__irq_line(state.kvm, AUX_IRQ, mlevel);
+}
+
+/*
+ * Add a byte to the mouse queue, then set IRQs
+ */
+void mouse_queue(u8 c)
+{
+	if (state.mcount >= QUEUE_SIZE)
+		return;
+
+	state.mq[state.mwrite++ % QUEUE_SIZE] = c;
+
+	state.mcount++;
+	kbd_update_irq();
+}
+
+/*
+ * Add a byte to the keyboard queue, then set IRQs
+ */
+void kbd_queue(u8 c)
+{
+	if (state.kcount >= QUEUE_SIZE)
+		return;
+
+	state.kq[state.kwrite++ % QUEUE_SIZE] = c;
+
+	state.kcount++;
+	kbd_update_irq();
+}
+
+static void kbd_write_command(struct kvm *kvm, u8 val)
+{
+	switch (val) {
+	case I8042_CMD_CTL_RCTR:
+		kbd_queue(state.mode);
+		break;
+	case I8042_CMD_CTL_WCTR:
+	case I8042_CMD_AUX_SEND:
+	case I8042_CMD_AUX_LOOP:
+		state.write_cmd = val;
+		break;
+	case I8042_CMD_AUX_TEST:
+		/* 0 means we're a normal PS/2 mouse */
+		mouse_queue(0);
+		break;
+	case I8042_CMD_AUX_DISABLE:
+		state.mode |= MODE_DISABLE_AUX;
+		break;
+	case I8042_CMD_AUX_ENABLE:
+		state.mode &= ~MODE_DISABLE_AUX;
+		break;
+	case I8042_CMD_SYSTEM_RESET:
+		kvm_cpu__reboot();
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * Called when the OS reads from port 0x60 (PS/2 data)
+ */
+static u32 kbd_read_data(void)
+{
+	u32 ret;
+	int i;
+
+	if (state.kcount != 0) {
+		/* Keyboard data gets read first */
+		ret = state.kq[state.kread++ % QUEUE_SIZE];
+		state.kcount--;
+		kvm__irq_line(state.kvm, KBD_IRQ, 0);
+		kbd_update_irq();
+	} else if (state.mcount > 0) {
+		/* Followed by the mouse */
+		ret = state.mq[state.mread++ % QUEUE_SIZE];
+		state.mcount--;
+		kvm__irq_line(state.kvm, AUX_IRQ, 0);
+		kbd_update_irq();
+	} else if (state.kcount == 0) {
+		i = state.kread - 1;
+		if (i < 0)
+			i = QUEUE_SIZE;
+		ret = state.kq[i];
+	}
+	return ret;
+}
+
+/*
+ * Called when the OS read from port 0x64, the command port
+ */
+static u32 kbd_read_status(void)
+{
+	return (u32)state.status;
+}
+
+/*
+ * Called when the OS writes to port 0x60 (data port)
+ * Things written here are generally arguments to commands previously
+ * written to port 0x64 and stored in state.write_cmd
+ */
+static void kbd_write_data(u32 val)
+{
+	switch (state.write_cmd) {
+	case I8042_CMD_CTL_WCTR:
+		state.mode = val;
+		kbd_update_irq();
+		break;
+	case I8042_CMD_AUX_LOOP:
+		mouse_queue(val);
+		mouse_queue(RESPONSE_ACK);
+		break;
+	case I8042_CMD_AUX_SEND:
+		/* The OS wants to send a command to the mouse */
+		mouse_queue(RESPONSE_ACK);
+		switch (val) {
+		case 0xe6:
+			/* set scaling = 1:1 */
+			state.mstatus &= ~AUX_SCALING_FLAG;
+			break;
+		case 0xe8:
+			/* set resolution */
+			state.mres = val;
+			break;
+		case 0xe9:
+			/* Report mouse status/config */
+			mouse_queue(state.mstatus);
+			mouse_queue(state.mres);
+			mouse_queue(state.msample);
+			break;
+		case 0xf2:
+			/* send ID */
+			mouse_queue(0); /* normal mouse */
+			break;
+		case 0xf3:
+			/* set sample rate */
+			state.msample = val;
+			break;
+		case 0xf4:
+			/* enable reporting */
+			state.mstatus |= AUX_ENABLE_REPORTING;
+			break;
+		case 0xf5:
+			state.mstatus &= ~AUX_ENABLE_REPORTING;
+			break;
+		case 0xf6:
+			/* set defaults, just fall through to reset */
+		case 0xff:
+			/* reset */
+			state.mstatus = 0x0;
+			state.mres = AUX_DEFAULT_RESOLUTION;
+			state.msample = AUX_DEFAULT_SAMPLE;
+			break;
+		default:
+			break;
+	}
+	break;
+	case 0:
+		/* Just send the ID */
+		kbd_queue(RESPONSE_ACK);
+		kbd_queue(0xab);
+		kbd_queue(0x41);
+		kbd_update_irq();
+		break;
+	default:
+		/* Yeah whatever */
+		break;
+	}
+	state.write_cmd = 0;
+}
+
+static void kbd_reset(void)
+{
+	state = (struct kbd_state) {
+		.status		= I8042_STR_MUXERR | I8042_STR_CMDDAT | I8042_STR_KEYLOCK, /* 0x1c */
+		.mode		= KBD_MODE_KBD_INT | KBD_MODE_SYS, /* 0x3 */
+		.mres		= AUX_DEFAULT_RESOLUTION,
+		.msample	= AUX_DEFAULT_SAMPLE,
+	};
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	switch (port) {
+	case I8042_COMMAND_REG: {
+		u8 value = kbd_read_status();
+		ioport__write8(data, value);
+		break;
+	}
+	case I8042_DATA_REG: {
+		u32 value = kbd_read_data();
+		ioport__write32(data, value);
+		break;
+	}
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+static bool kbd_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	switch (port) {
+	case I8042_COMMAND_REG: {
+		u8 value = ioport__read8(data);
+		kbd_write_command(kvm, value);
+		break;
+	}
+	case I8042_DATA_REG: {
+		u32 value = ioport__read32(data);
+		kbd_write_data(value);
+		break;
+	}
+	default:
+		return false;
+	}
+
+	return true;
+}
+
+static struct ioport_operations kbd_ops = {
+	.io_in		= kbd_in,
+	.io_out		= kbd_out,
+};
+
+void kbd__init(struct kvm *kvm)
+{
+	kbd_reset();
+	state.kvm = kvm;
+	ioport__register(I8042_DATA_REG, &kbd_ops, 2, NULL);
+	ioport__register(I8042_COMMAND_REG, &kbd_ops, 2, NULL);
+}
diff --git a/tools/kvm/hw/pci-shmem.c b/tools/kvm/hw/pci-shmem.c
new file mode 100644
index 0000000..6130131
--- /dev/null
+++ b/tools/kvm/hw/pci-shmem.c
@@ -0,0 +1,262 @@
+#include "kvm/pci-shmem.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/util.h"
+#include "kvm/ioport.h"
+#include "kvm/ioeventfd.h"
+
+#include <linux/kvm.h>
+#include <linux/byteorder.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+static struct pci_device_header pci_shmem_pci_device = {
+	.vendor_id	= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+	.device_id	= cpu_to_le16(0x1110),
+	.header_type	= PCI_HEADER_TYPE_NORMAL,
+	.class[2]	= 0xFF,	/* misc pci device */
+	.status		= cpu_to_le16(PCI_STATUS_CAP_LIST),
+	.capabilities	= (void *)&pci_shmem_pci_device.msix - (void *)&pci_shmem_pci_device,
+	.msix.cap	= PCI_CAP_ID_MSIX,
+	.msix.ctrl	= cpu_to_le16(1),
+	.msix.table_offset = cpu_to_le32(1),		/* Use BAR 1 */
+	.msix.pba_offset = cpu_to_le32(0x1001),		/* Use BAR 1 */
+};
+
+/* registers for the Inter-VM shared memory device */
+enum ivshmem_registers {
+	INTRMASK = 0,
+	INTRSTATUS = 4,
+	IVPOSITION = 8,
+	DOORBELL = 12,
+};
+
+static struct shmem_info *shmem_region;
+static u16 ivshmem_registers;
+static int local_fd;
+static u32 local_id;
+static u64 msix_block;
+static u64 msix_pba;
+static struct msix_table msix_table[2];
+
+int pci_shmem__register_mem(struct shmem_info *si)
+{
+	if (shmem_region == NULL) {
+		shmem_region = si;
+	} else {
+		pr_warning("only single shmem currently avail. ignoring.\n");
+		free(si);
+	}
+	return 0;
+}
+
+static bool shmem_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	u16 offset = port - ivshmem_registers;
+
+	switch (offset) {
+	case INTRMASK:
+		break;
+	case INTRSTATUS:
+		break;
+	case IVPOSITION:
+		ioport__write32(data, local_id);
+		break;
+	case DOORBELL:
+		break;
+	};
+
+	return true;
+}
+
+static bool shmem_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	u16 offset = port - ivshmem_registers;
+
+	switch (offset) {
+	case INTRMASK:
+		break;
+	case INTRSTATUS:
+		break;
+	case IVPOSITION:
+		break;
+	case DOORBELL:
+		break;
+	};
+
+	return true;
+}
+
+static struct ioport_operations shmem_pci__io_ops = {
+	.io_in	= shmem_pci__io_in,
+	.io_out	= shmem_pci__io_out,
+};
+
+static void callback_mmio_msix(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+{
+	void *mem;
+
+	if (addr - msix_block < 0x1000)
+		mem = &msix_table;
+	else
+		mem = &msix_pba;
+
+	if (is_write)
+		memcpy(mem + addr - msix_block, data, len);
+	else
+		memcpy(data, mem + addr - msix_block, len);
+}
+
+/*
+ * Return an irqfd which can be used by other guests to signal this guest
+ * whenever they need to poke it
+ */
+int pci_shmem__get_local_irqfd(struct kvm *kvm)
+{
+	int fd, gsi, r;
+	struct kvm_irqfd irqfd;
+
+	if (local_fd == 0) {
+		fd = eventfd(0, 0);
+		if (fd < 0)
+			return fd;
+
+		if (pci_shmem_pci_device.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
+			gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
+		} else {
+			gsi = pci_shmem_pci_device.irq_line;
+		}
+
+		irqfd = (struct kvm_irqfd) {
+			.fd = fd,
+			.gsi = gsi,
+		};
+
+		r = ioctl(kvm->vm_fd, KVM_IRQFD, &irqfd);
+		if (r < 0)
+			return r;
+
+		local_fd = fd;
+	}
+
+	return local_fd;
+}
+
+/*
+ * Connect a new client to ivshmem by adding the appropriate datamatch
+ * to the DOORBELL
+ */
+int pci_shmem__add_client(struct kvm *kvm, u32 id, int fd)
+{
+	struct kvm_ioeventfd ioevent;
+
+	ioevent = (struct kvm_ioeventfd) {
+		.addr		= ivshmem_registers + DOORBELL,
+		.len		= sizeof(u32),
+		.datamatch	= id,
+		.fd		= fd,
+		.flags		= KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
+	};
+
+	return ioctl(kvm->vm_fd, KVM_IOEVENTFD, &ioevent);
+}
+
+/*
+ * Remove a client connected to ivshmem by removing the appropriate datamatch
+ * from the DOORBELL
+ */
+int pci_shmem__remove_client(struct kvm *kvm, u32 id)
+{
+	struct kvm_ioeventfd ioevent;
+
+	ioevent = (struct kvm_ioeventfd) {
+		.addr		= ivshmem_registers + DOORBELL,
+		.len		= sizeof(u32),
+		.datamatch	= id,
+		.flags		= KVM_IOEVENTFD_FLAG_PIO
+				| KVM_IOEVENTFD_FLAG_DATAMATCH
+				| KVM_IOEVENTFD_FLAG_DEASSIGN,
+	};
+
+	return ioctl(kvm->vm_fd, KVM_IOEVENTFD, &ioevent);
+}
+
+static void *setup_shmem(const char *key, size_t len, int creating)
+{
+	int fd;
+	int rtn;
+	void *mem;
+	int flag = O_RDWR;
+
+	if (creating)
+		flag |= O_CREAT;
+
+	fd = shm_open(key, flag, S_IRUSR | S_IWUSR);
+	if (fd < 0) {
+		pr_warning("Failed to open shared memory file %s\n", key);
+		return NULL;
+	}
+
+	if (creating) {
+		rtn = ftruncate(fd, (off_t) len);
+		if (rtn < 0)
+			pr_warning("Can't ftruncate(fd,%zu)\n", len);
+	}
+	mem = mmap(NULL, len,
+		   PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, fd, 0);
+	close(fd);
+
+	if (mem == NULL)
+		pr_warning("Failed to mmap shared memory file");
+
+	return mem;
+}
+
+int pci_shmem__init(struct kvm *kvm)
+{
+	u8 dev, line, pin;
+	char *mem;
+
+	if (shmem_region == 0)
+		return 0;
+
+	/* Register good old INTx */
+	if (irq__register_device(PCI_DEVICE_ID_PCI_SHMEM, &dev, &pin, &line) < 0)
+		return 0;
+
+	pci_shmem_pci_device.irq_pin = pin;
+	pci_shmem_pci_device.irq_line = line;
+
+	/* Register MMIO space for MSI-X */
+	ivshmem_registers = ioport__register(IOPORT_EMPTY, &shmem_pci__io_ops, IOPORT_SIZE, NULL);
+	msix_block = pci_get_io_space_block(0x1010);
+	kvm__register_mmio(kvm, msix_block, 0x1010, false, callback_mmio_msix, NULL);
+
+	/*
+	 * This registers 3 BARs:
+	 *
+	 * 0 - ivshmem registers
+	 * 1 - MSI-X MMIO space
+	 * 2 - Shared memory block
+	 */
+	pci_shmem_pci_device.bar[0] = cpu_to_le32(ivshmem_registers | PCI_BASE_ADDRESS_SPACE_IO);
+	pci_shmem_pci_device.bar_size[0] = shmem_region->size;
+	pci_shmem_pci_device.bar[1] = cpu_to_le32(msix_block | PCI_BASE_ADDRESS_SPACE_MEMORY);
+	pci_shmem_pci_device.bar_size[1] = 0x1010;
+	pci_shmem_pci_device.bar[2] = cpu_to_le32(shmem_region->phys_addr | PCI_BASE_ADDRESS_SPACE_MEMORY);
+	pci_shmem_pci_device.bar_size[2] = shmem_region->size;
+
+	pci__register(&pci_shmem_pci_device, dev);
+
+	/* Open shared memory and plug it into the guest */
+	mem = setup_shmem(shmem_region->handle, shmem_region->size,
+				shmem_region->create);
+	if (mem == NULL)
+		return 0;
+	kvm__register_mem(kvm, shmem_region->phys_addr, shmem_region->size,
+			  mem);
+	return 1;
+}
diff --git a/tools/kvm/hw/rtc.c b/tools/kvm/hw/rtc.c
new file mode 100644
index 0000000..6d4a05a
--- /dev/null
+++ b/tools/kvm/hw/rtc.c
@@ -0,0 +1,118 @@
+#include "kvm/rtc.h"
+
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+
+#include <time.h>
+
+/*
+ * MC146818 RTC registers
+ */
+#define RTC_SECONDS			0x00
+#define RTC_SECONDS_ALARM		0x01
+#define RTC_MINUTES			0x02
+#define RTC_MINUTES_ALARM		0x03
+#define RTC_HOURS			0x04
+#define RTC_HOURS_ALARM			0x05
+#define RTC_DAY_OF_WEEK			0x06
+#define RTC_DAY_OF_MONTH		0x07
+#define RTC_MONTH			0x08
+#define RTC_YEAR			0x09
+
+#define RTC_REG_A			0x0A
+#define RTC_REG_B			0x0B
+#define RTC_REG_C			0x0C
+#define RTC_REG_D			0x0D
+
+struct rtc_device {
+	u8			cmos_idx;
+	u8			cmos_data[128];
+};
+
+static struct rtc_device	rtc;
+
+static inline unsigned char bin2bcd(unsigned val)
+{
+	return ((val / 10) << 4) + val % 10;
+}
+
+static bool cmos_ram_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	struct tm *tm;
+	time_t ti;
+
+	time(&ti);
+
+	tm = gmtime(&ti);
+
+	switch (rtc.cmos_idx) {
+	case RTC_SECONDS:
+		ioport__write8(data, bin2bcd(tm->tm_sec));
+		break;
+	case RTC_MINUTES:
+		ioport__write8(data, bin2bcd(tm->tm_min));
+		break;
+	case RTC_HOURS:
+		ioport__write8(data, bin2bcd(tm->tm_hour));
+		break;
+	case RTC_DAY_OF_WEEK:
+		ioport__write8(data, bin2bcd(tm->tm_wday + 1));
+		break;
+	case RTC_DAY_OF_MONTH:
+		ioport__write8(data, bin2bcd(tm->tm_mday));
+		break;
+	case RTC_MONTH:
+		ioport__write8(data, bin2bcd(tm->tm_mon + 1));
+		break;
+	case RTC_YEAR:
+		ioport__write8(data, bin2bcd(tm->tm_year));
+		break;
+	default:
+		ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
+		break;
+	}
+
+	return true;
+}
+
+static bool cmos_ram_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	switch (rtc.cmos_idx) {
+	case RTC_REG_C:
+	case RTC_REG_D:
+		/* Read-only */
+		break;
+	default:
+		rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+		break;
+	}
+
+	return true;
+}
+
+static struct ioport_operations cmos_ram_data_ioport_ops = {
+	.io_out		= cmos_ram_data_out,
+	.io_in		= cmos_ram_data_in,
+};
+
+static bool cmos_ram_index_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	u8 value = ioport__read8(data);
+
+	kvm->nmi_disabled	= value & (1UL << 7);
+
+	rtc.cmos_idx		= value & ~(1UL << 7);
+
+	return true;
+}
+
+static struct ioport_operations cmos_ram_index_ioport_ops = {
+	.io_out		= cmos_ram_index_out,
+};
+
+void rtc__init(void)
+{
+	/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+	ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+	ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
+}
diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
new file mode 100644
index 0000000..d1d67b0
--- /dev/null
+++ b/tools/kvm/hw/serial.c
@@ -0,0 +1,414 @@
+#include "kvm/8250-serial.h"
+
+#include "kvm/read-write.h"
+#include "kvm/ioport.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/kvm.h"
+
+#include <linux/types.h>
+#include <linux/serial_reg.h>
+
+#include <pthread.h>
+
+/*
+ * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
+ * expects that for autodetection.
+ */
+#define FIFO_LEN		64
+#define FIFO_MASK		(FIFO_LEN - 1)
+
+#define UART_IIR_TYPE_BITS	0xc0
+
+struct serial8250_device {
+	pthread_mutex_t		mutex;
+	u8			id;
+
+	u16			iobase;
+	u8			irq;
+	u8			irq_state;
+	int			txcnt;
+	int			rxcnt;
+	int			rxdone;
+	char			txbuf[FIFO_LEN];
+	char			rxbuf[FIFO_LEN];
+
+	u8			dll;
+	u8			dlm;
+	u8			iir;
+	u8			ier;
+	u8			fcr;
+	u8			lcr;
+	u8			mcr;
+	u8			lsr;
+	u8			msr;
+	u8			scr;
+};
+
+#define SERIAL_REGS_SETTING \
+	.iir			= UART_IIR_NO_INT, \
+	.lsr			= UART_LSR_TEMT | UART_LSR_THRE, \
+	.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
+	.mcr			= UART_MCR_OUT2,
+
+static struct serial8250_device devices[] = {
+	/* ttyS0 */
+	[0]	= {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+
+		.id			= 0,
+		.iobase			= 0x3f8,
+		.irq			= 4,
+
+		SERIAL_REGS_SETTING
+	},
+	/* ttyS1 */
+	[1]	= {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+
+		.id			= 1,
+		.iobase			= 0x2f8,
+		.irq			= 3,
+
+		SERIAL_REGS_SETTING
+	},
+	/* ttyS2 */
+	[2]	= {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+
+		.id			= 2,
+		.iobase			= 0x3e8,
+		.irq			= 4,
+
+		SERIAL_REGS_SETTING
+	},
+	/* ttyS3 */
+	[3]	= {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+
+		.id			= 3,
+		.iobase			= 0x2e8,
+		.irq			= 3,
+
+		SERIAL_REGS_SETTING
+	},
+};
+
+static void serial8250_flush_tx(struct serial8250_device *dev)
+{
+	dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+
+	if (dev->txcnt) {
+		term_putc(CONSOLE_8250, dev->txbuf, dev->txcnt, dev->id);
+		dev->txcnt = 0;
+	}
+}
+
+static void serial8250_update_irq(struct kvm *kvm, struct serial8250_device *dev)
+{
+	u8 iir = 0;
+
+	/* Handle clear rx */
+	if (dev->lcr & UART_FCR_CLEAR_RCVR) {
+		dev->lcr &= ~UART_FCR_CLEAR_RCVR;
+		dev->rxcnt = dev->rxdone = 0;
+		dev->lsr &= ~UART_LSR_DR;
+	}
+
+	/* Handle clear tx */
+	if (dev->lcr & UART_FCR_CLEAR_XMIT) {
+		dev->lcr &= ~UART_FCR_CLEAR_XMIT;
+		dev->txcnt = 0;
+		dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE;
+	}
+
+	/* Data ready and rcv interrupt enabled ? */
+	if ((dev->ier & UART_IER_RDI) && (dev->lsr & UART_LSR_DR))
+		iir |= UART_IIR_RDI;
+
+	/* Transmitter empty and interrupt enabled ? */
+	if ((dev->ier & UART_IER_THRI) && (dev->lsr & UART_LSR_TEMT))
+		iir |= UART_IIR_THRI;
+
+	/* Now update the irq line, if necessary */
+	if (!iir) {
+		dev->iir = UART_IIR_NO_INT;
+		if (dev->irq_state)
+			kvm__irq_line(kvm, dev->irq, 0);
+	} else {
+		dev->iir = iir;
+		if (!dev->irq_state)
+			kvm__irq_line(kvm, dev->irq, 1);
+	}
+	dev->irq_state = iir;
+
+	/*
+	 * If the kernel disabled the tx interrupt, we know that there
+	 * is nothing more to transmit, so we can reset our tx logic
+	 * here.
+	 */
+	if (!(dev->ier & UART_IER_THRI))
+		serial8250_flush_tx(dev);
+}
+
+#define SYSRQ_PENDING_NONE		0
+#define SYSRQ_PENDING_BREAK		1
+
+static int sysrq_pending;
+
+static void serial8250__sysrq(struct kvm *kvm, struct serial8250_device *dev)
+{
+	dev->lsr |= UART_LSR_DR | UART_LSR_BI;
+	dev->rxbuf[dev->rxcnt++] = 'p';
+	sysrq_pending	= SYSRQ_PENDING_NONE;
+}
+
+static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev,
+				bool handle_sysrq)
+{
+	int c;
+
+	/*
+	 * If the guest transmitted a full fifo, we clear the
+	 * TEMT/THRE bits to let the kernel escape from the 8250
+	 * interrupt handler. We come here only once a ms, so that
+	 * should give the kernel the desired pause. That also flushes
+	 * the tx fifo to the terminal.
+	 */
+	serial8250_flush_tx(dev);
+
+	if (dev->mcr & UART_MCR_LOOP)
+		return;
+
+	if ((dev->lsr & UART_LSR_DR) || dev->rxcnt)
+		return;
+
+	if (handle_sysrq && sysrq_pending) {
+		serial8250__sysrq(kvm, dev);
+		return;
+	}
+
+	while (term_readable(CONSOLE_8250, dev->id) &&
+	       dev->rxcnt < FIFO_LEN) {
+
+		c = term_getc(CONSOLE_8250, dev->id);
+
+		if (c < 0)
+			break;
+		dev->rxbuf[dev->rxcnt++] = c;
+		dev->lsr |= UART_LSR_DR;
+	}
+}
+
+void serial8250__update_consoles(struct kvm *kvm)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(devices); i++) {
+		struct serial8250_device *dev = &devices[i];
+
+		mutex_lock(&dev->mutex);
+
+		/* Restrict sysrq injection to the first port */
+		serial8250__receive(kvm, dev, i == 0);
+
+		serial8250_update_irq(kvm, dev);
+
+		mutex_unlock(&dev->mutex);
+	}
+}
+
+void serial8250__inject_sysrq(struct kvm *kvm)
+{
+	sysrq_pending	= SYSRQ_PENDING_BREAK;
+}
+
+static struct serial8250_device *find_device(u16 port)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(devices); i++) {
+		struct serial8250_device *dev = &devices[i];
+
+		if (dev->iobase == (port & ~0x7))
+			return dev;
+	}
+	return NULL;
+}
+
+static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port,
+			   void *data, int size)
+{
+	struct serial8250_device *dev;
+	u16 offset;
+	bool ret = true;
+	char *addr = data;
+
+	dev = find_device(port);
+	if (!dev)
+		return false;
+
+	mutex_lock(&dev->mutex);
+
+	offset = port - dev->iobase;
+
+	switch (offset) {
+	case UART_TX:
+		if (dev->lcr & UART_LCR_DLAB) {
+			dev->dll = ioport__read8(data);
+			break;
+		}
+
+		/* Loopback mode */
+		if (dev->mcr & UART_MCR_LOOP) {
+			if (dev->rxcnt < FIFO_LEN) {
+				dev->rxbuf[dev->rxcnt++] = *addr;
+				dev->lsr |= UART_LSR_DR;
+			}
+			break;
+		}
+
+		if (dev->txcnt < FIFO_LEN) {
+			dev->txbuf[dev->txcnt++] = *addr;
+			dev->lsr &= ~UART_LSR_TEMT;
+			if (dev->txcnt == FIFO_LEN / 2)
+				dev->lsr &= ~UART_LSR_THRE;
+		} else {
+			/* Should never happpen */
+			dev->lsr &= ~(UART_LSR_TEMT | UART_LSR_THRE);
+		}
+		break;
+	case UART_IER:
+		if (!(dev->lcr & UART_LCR_DLAB))
+			dev->ier = ioport__read8(data) & 0x0f;
+		else
+			dev->dlm = ioport__read8(data);
+		break;
+	case UART_FCR:
+		dev->fcr = ioport__read8(data);
+		break;
+	case UART_LCR:
+		dev->lcr = ioport__read8(data);
+		break;
+	case UART_MCR:
+		dev->mcr = ioport__read8(data);
+		break;
+	case UART_LSR:
+		/* Factory test */
+		break;
+	case UART_MSR:
+		/* Not used */
+		break;
+	case UART_SCR:
+		dev->scr = ioport__read8(data);
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	serial8250_update_irq(kvm, dev);
+
+	mutex_unlock(&dev->mutex);
+
+	return ret;
+}
+
+static void serial8250_rx(struct serial8250_device *dev, void *data)
+{
+	if (dev->rxdone == dev->rxcnt)
+		return;
+
+	/* Break issued ? */
+	if (dev->lsr & UART_LSR_BI) {
+		dev->lsr &= ~UART_LSR_BI;
+		ioport__write8(data, 0);
+		return;
+	}
+
+	ioport__write8(data, dev->rxbuf[dev->rxdone++]);
+	if (dev->rxcnt == dev->rxdone) {
+		dev->lsr &= ~UART_LSR_DR;
+		dev->rxcnt = dev->rxdone = 0;
+	}
+}
+
+static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	struct serial8250_device *dev;
+	u16 offset;
+	bool ret = true;
+
+	dev = find_device(port);
+	if (!dev)
+		return false;
+
+	mutex_lock(&dev->mutex);
+
+	offset = port - dev->iobase;
+
+	switch (offset) {
+	case UART_RX:
+		if (dev->lcr & UART_LCR_DLAB)
+			ioport__write8(data, dev->dll);
+		else
+			serial8250_rx(dev, data);
+		break;
+	case UART_IER:
+		if (dev->lcr & UART_LCR_DLAB)
+			ioport__write8(data, dev->dlm);
+		else
+			ioport__write8(data, dev->ier);
+		break;
+	case UART_IIR:
+		ioport__write8(data, dev->iir | UART_IIR_TYPE_BITS);
+		break;
+	case UART_LCR:
+		ioport__write8(data, dev->lcr);
+		break;
+	case UART_MCR:
+		ioport__write8(data, dev->mcr);
+		break;
+	case UART_LSR:
+		ioport__write8(data, dev->lsr);
+		break;
+	case UART_MSR:
+		ioport__write8(data, dev->msr);
+		break;
+	case UART_SCR:
+		ioport__write8(data, dev->scr);
+		break;
+	default:
+		ret = false;
+		break;
+	}
+
+	serial8250_update_irq(kvm, dev);
+
+	mutex_unlock(&dev->mutex);
+
+	return ret;
+}
+
+static struct ioport_operations serial8250_ops = {
+	.io_in		= serial8250_in,
+	.io_out		= serial8250_out,
+};
+
+static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
+{
+	ioport__register(dev->iobase, &serial8250_ops, 8, NULL);
+	kvm__irq_line(kvm, dev->irq, 0);
+}
+
+void serial8250__init(struct kvm *kvm)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(devices); i++) {
+		struct serial8250_device *dev = &devices[i];
+
+		serial8250__device_init(kvm, dev);
+	}
+}
diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
new file mode 100644
index 0000000..63f1082
--- /dev/null
+++ b/tools/kvm/hw/vesa.c
@@ -0,0 +1,78 @@
+#include "kvm/vesa.h"
+
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/framebuffer.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include <linux/byteorder.h>
+#include <sys/mman.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+static bool vesa_pci_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	return true;
+}
+
+static bool vesa_pci_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	return true;
+}
+
+static struct ioport_operations vesa_io_ops = {
+	.io_in			= vesa_pci_io_in,
+	.io_out			= vesa_pci_io_out,
+};
+
+static struct pci_device_header vesa_pci_device = {
+	.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+	.device_id		= cpu_to_le16(PCI_DEVICE_ID_VESA),
+	.header_type		= PCI_HEADER_TYPE_NORMAL,
+	.revision_id		= 0,
+	.class[2]		= 0x03,
+	.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+	.subsys_id		= cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
+	.bar[1]			= cpu_to_le32(VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY),
+	.bar_size[1]		= VESA_MEM_SIZE,
+};
+
+static struct framebuffer vesafb;
+
+struct framebuffer *vesa__init(struct kvm *kvm)
+{
+	u16 vesa_base_addr;
+	u8 dev, line, pin;
+	char *mem;
+
+	if (irq__register_device(PCI_DEVICE_ID_VESA, &dev, &pin, &line) < 0)
+		return NULL;
+
+	vesa_pci_device.irq_pin		= pin;
+	vesa_pci_device.irq_line	= line;
+	vesa_base_addr			= ioport__register(IOPORT_EMPTY, &vesa_io_ops, IOPORT_SIZE, NULL);
+	vesa_pci_device.bar[0]		= cpu_to_le32(vesa_base_addr | PCI_BASE_ADDRESS_SPACE_IO);
+	pci__register(&vesa_pci_device, dev);
+
+	mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+	if (mem == MAP_FAILED)
+		return NULL;
+
+	kvm__register_mem(kvm, VESA_MEM_ADDR, VESA_MEM_SIZE, mem);
+
+	vesafb = (struct framebuffer) {
+		.width			= VESA_WIDTH,
+		.height			= VESA_HEIGHT,
+		.depth			= VESA_BPP,
+		.mem			= mem,
+		.mem_addr		= VESA_MEM_ADDR,
+		.mem_size		= VESA_MEM_SIZE,
+	};
+	return fb__register(&vesafb);
+}
diff --git a/tools/kvm/include/asm/hweight.h b/tools/kvm/include/asm/hweight.h
new file mode 100644
index 0000000..1a43977
--- /dev/null
+++ b/tools/kvm/include/asm/hweight.h
@@ -0,0 +1,8 @@
+#ifndef _KVM_ASM_HWEIGHT_H_
+#define _KVM_ASM_HWEIGHT_H_
+
+#include <linux/types.h>
+unsigned int hweight32(unsigned int w);
+unsigned long hweight64(__u64 w);
+
+#endif /* _KVM_ASM_HWEIGHT_H_ */
diff --git a/tools/kvm/include/bios/memcpy.h b/tools/kvm/include/bios/memcpy.h
new file mode 100644
index 0000000..e021044
--- /dev/null
+++ b/tools/kvm/include/bios/memcpy.h
@@ -0,0 +1,9 @@
+#ifndef KVM_BIOS_MEMCPY_H
+#define KVM_BIOS_MEMCPY_H
+
+#include <linux/types.h>
+#include <stddef.h>
+
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len);
+
+#endif /* KVM_BIOS_MEMCPY_H */
diff --git a/tools/kvm/include/kvm/8250-serial.h b/tools/kvm/include/kvm/8250-serial.h
new file mode 100644
index 0000000..8bd8798
--- /dev/null
+++ b/tools/kvm/include/kvm/8250-serial.h
@@ -0,0 +1,10 @@
+#ifndef KVM__8250_SERIAL_H
+#define KVM__8250_SERIAL_H
+
+struct kvm;
+
+void serial8250__init(struct kvm *kvm);
+void serial8250__update_consoles(struct kvm *kvm);
+void serial8250__inject_sysrq(struct kvm *kvm);
+
+#endif /* KVM__8250_SERIAL_H */
diff --git a/tools/kvm/include/kvm/apic.h b/tools/kvm/include/kvm/apic.h
new file mode 100644
index 0000000..2129997
--- /dev/null
+++ b/tools/kvm/include/kvm/apic.h
@@ -0,0 +1,17 @@
+#ifndef KVM_APIC_H_
+#define KVM_APIC_H_
+
+#include <asm/apicdef.h>
+
+/*
+ * APIC, IOAPIC stuff
+ */
+#define APIC_BASE_ADDR_STEP	0x00400000
+#define IOAPIC_BASE_ADDR_STEP	0x00100000
+
+#define APIC_ADDR(apic)		(APIC_DEFAULT_PHYS_BASE + apic * APIC_BASE_ADDR_STEP)
+#define IOAPIC_ADDR(ioapic)	(IO_APIC_DEFAULT_PHYS_BASE + ioapic * IOAPIC_BASE_ADDR_STEP)
+
+#define KVM_APIC_VERSION	0x14 /* xAPIC */
+
+#endif /* KVM_APIC_H_ */
diff --git a/tools/kvm/include/kvm/brlock.h b/tools/kvm/include/kvm/brlock.h
new file mode 100644
index 0000000..bd1d882
--- /dev/null
+++ b/tools/kvm/include/kvm/brlock.h
@@ -0,0 +1,41 @@
+#ifndef KVM__BRLOCK_H
+#define KVM__BRLOCK_H
+
+#include "kvm/kvm.h"
+#include "kvm/barrier.h"
+
+/*
+ * brlock is a lock which is very cheap for reads, but very expensive
+ * for writes.
+ * This lock will be used when updates are very rare and reads are common.
+ * This lock is currently implemented by stopping the guest while
+ * performing the updates. We assume that the only threads whichread from
+ * the locked data are VCPU threads, and the only writer isn't a VCPU thread.
+ */
+
+#ifndef barrier
+#define barrier()		__asm__ __volatile__("": : :"memory")
+#endif
+
+#ifdef KVM_BRLOCK_DEBUG
+
+#include "kvm/rwsem.h"
+
+DECLARE_RWSEM(brlock_sem);
+
+#define br_read_lock()		down_read(&brlock_sem);
+#define br_read_unlock()	up_read(&brlock_sem);
+
+#define br_write_lock()		down_write(&brlock_sem);
+#define br_write_unlock()	up_write(&brlock_sem);
+
+#else
+
+#define br_read_lock()		barrier()
+#define br_read_unlock()	barrier()
+
+#define br_write_lock()		kvm__pause()
+#define br_write_unlock()	kvm__continue()
+#endif
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-balloon.h b/tools/kvm/include/kvm/builtin-balloon.h
new file mode 100644
index 0000000..77ee656
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-balloon.h
@@ -0,0 +1,9 @@
+#ifndef KVM__BALLOON_H
+#define KVM__BALLOON_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_balloon(int argc, const char **argv, const char *prefix);
+void kvm_balloon_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-debug.h b/tools/kvm/include/kvm/builtin-debug.h
new file mode 100644
index 0000000..6105a8c
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-debug.h
@@ -0,0 +1,18 @@
+#ifndef KVM__DEBUG_H
+#define KVM__DEBUG_H
+
+#include <kvm/util.h>
+#include <linux/types.h>
+
+#define KVM_DEBUG_CMD_TYPE_DUMP	(1 << 0)
+#define KVM_DEBUG_CMD_TYPE_NMI	(1 << 1)
+
+struct debug_cmd_params {
+	u32 dbg_type;
+	u32 cpu;
+};
+
+int kvm_cmd_debug(int argc, const char **argv, const char *prefix);
+void kvm_debug_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-help.h b/tools/kvm/include/kvm/builtin-help.h
new file mode 100644
index 0000000..2946743
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-help.h
@@ -0,0 +1,6 @@
+#ifndef __KVM_HELP_H__
+#define __KVM_HELP_H__
+
+int kvm_cmd_help(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-list.h b/tools/kvm/include/kvm/builtin-list.h
new file mode 100644
index 0000000..47029ca
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-list.h
@@ -0,0 +1,10 @@
+#ifndef KVM__LIST_H
+#define KVM__LIST_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_list(int argc, const char **argv, const char *prefix);
+void kvm_list_help(void) NORETURN;
+int get_vmstate(int sock);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-pause.h b/tools/kvm/include/kvm/builtin-pause.h
new file mode 100644
index 0000000..84aaee3
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-pause.h
@@ -0,0 +1,9 @@
+#ifndef KVM__PAUSE_H
+#define KVM__PAUSE_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_pause(int argc, const char **argv, const char *prefix);
+void kvm_pause_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-resume.h b/tools/kvm/include/kvm/builtin-resume.h
new file mode 100644
index 0000000..7de999b
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-resume.h
@@ -0,0 +1,9 @@
+#ifndef KVM__RESUME_H
+#define KVM__RESUME_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_resume(int argc, const char **argv, const char *prefix);
+void kvm_resume_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-run.h b/tools/kvm/include/kvm/builtin-run.h
new file mode 100644
index 0000000..91521a5
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-run.h
@@ -0,0 +1,11 @@
+#ifndef __KVM_RUN_H__
+#define __KVM_RUN_H__
+
+#include <kvm/util.h>
+
+int kvm_cmd_run(int argc, const char **argv, const char *prefix);
+void kvm_run_help(void) NORETURN;
+
+void kvm_run_set_wrapper_sandbox(void);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-sandbox.h b/tools/kvm/include/kvm/builtin-sandbox.h
new file mode 100644
index 0000000..98cd6be
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-sandbox.h
@@ -0,0 +1,6 @@
+#ifndef KVM__SANDBOX_H
+#define KVM__SANDBOX_H
+
+int kvm_cmd_sandbox(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-setup.h b/tools/kvm/include/kvm/builtin-setup.h
new file mode 100644
index 0000000..4a8d7ee
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-setup.h
@@ -0,0 +1,11 @@
+#ifndef KVM__SETUP_H
+#define KVM__SETUP_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_setup(int argc, const char **argv, const char *prefix);
+void kvm_setup_help(void) NORETURN;
+int kvm_setup_create_new(const char *guestfs_name);
+void kvm_setup_resolv(const char *guestfs_name);
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-stat.h b/tools/kvm/include/kvm/builtin-stat.h
new file mode 100644
index 0000000..4fecb37
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-stat.h
@@ -0,0 +1,9 @@
+#ifndef KVM__STAT_H
+#define KVM__STAT_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_stat(int argc, const char **argv, const char *prefix);
+void kvm_stat_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-stop.h b/tools/kvm/include/kvm/builtin-stop.h
new file mode 100644
index 0000000..b26b275
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-stop.h
@@ -0,0 +1,9 @@
+#ifndef KVM__STOP_H
+#define KVM__STOP_H
+
+#include <kvm/util.h>
+
+int kvm_cmd_stop(int argc, const char **argv, const char *prefix);
+void kvm_stop_help(void) NORETURN;
+
+#endif
diff --git a/tools/kvm/include/kvm/builtin-version.h b/tools/kvm/include/kvm/builtin-version.h
new file mode 100644
index 0000000..83cac4d
--- /dev/null
+++ b/tools/kvm/include/kvm/builtin-version.h
@@ -0,0 +1,6 @@
+#ifndef KVM__VERSION_H
+#define KVM__VERSION_H
+
+int kvm_cmd_version(int argc, const char **argv, const char *prefix);
+
+#endif
diff --git a/tools/kvm/include/kvm/compiler.h b/tools/kvm/include/kvm/compiler.h
new file mode 100644
index 0000000..2013a83
--- /dev/null
+++ b/tools/kvm/include/kvm/compiler.h
@@ -0,0 +1,10 @@
+#ifndef KVM_COMPILER_H_
+#define KVM_COMPILER_H_
+
+#ifndef __compiletime_error
+# define __compiletime_error(message)
+#endif
+
+#define notrace __attribute__((no_instrument_function))
+
+#endif /* KVM_COMPILER_H_ */
diff --git a/tools/kvm/include/kvm/disk-image.h b/tools/kvm/include/kvm/disk-image.h
new file mode 100644
index 0000000..56c08da
--- /dev/null
+++ b/tools/kvm/include/kvm/disk-image.h
@@ -0,0 +1,81 @@
+#ifndef KVM__DISK_IMAGE_H
+#define KVM__DISK_IMAGE_H
+
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+
+#include <linux/types.h>
+#include <linux/fs.h>	/* for BLKGETSIZE64 */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <sys/uio.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define SECTOR_SHIFT		9
+#define SECTOR_SIZE		(1UL << SECTOR_SHIFT)
+
+enum {
+	DISK_IMAGE_REGULAR,
+	DISK_IMAGE_MMAP,
+};
+
+#define MAX_DISK_IMAGES         4
+
+struct disk_image;
+
+struct disk_image_operations {
+	ssize_t (*read_sector)(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param);
+	ssize_t (*write_sector)(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param);
+	int (*flush)(struct disk_image *disk);
+	int (*close)(struct disk_image *disk);
+};
+
+struct disk_image {
+	int				fd;
+	u64				size;
+	struct disk_image_operations	*ops;
+	void				*priv;
+	void				*disk_req_cb_param;
+	void				(*disk_req_cb)(void *param, long len);
+	bool				async;
+	int				evt;
+#ifdef CONFIG_HAS_AIO
+	io_context_t			ctx;
+#endif
+};
+
+struct disk_image *disk_image__open(const char *filename, bool readonly);
+struct disk_image **disk_image__open_all(const char **filenames, bool *readonly, int count);
+struct disk_image *disk_image__new(int fd, u64 size, struct disk_image_operations *ops, int mmap);
+int disk_image__close(struct disk_image *disk);
+void disk_image__close_all(struct disk_image **disks, int count);
+int disk_image__flush(struct disk_image *disk);
+ssize_t disk_image__read(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param);
+ssize_t disk_image__write(struct disk_image *disk, u64 sector, const struct iovec *iov,
+				int iovcount, void *param);
+ssize_t disk_image__get_serial(struct disk_image *disk, void *buffer, ssize_t *len);
+
+struct disk_image *raw_image__probe(int fd, struct stat *st, bool readonly);
+struct disk_image *blkdev__probe(const char *filename, struct stat *st);
+
+ssize_t raw_image__read_sector(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__write_sector(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__read_sector_mmap(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param);
+ssize_t raw_image__write_sector_mmap(struct disk_image *disk, u64 sector,
+				const struct iovec *iov, int iovcount, void *param);
+int raw_image__close(struct disk_image *disk);
+void disk_image__set_callback(struct disk_image *disk, void (*disk_req_cb)(void *param, long len));
+#endif /* KVM__DISK_IMAGE_H */
diff --git a/tools/kvm/include/kvm/e820.h b/tools/kvm/include/kvm/e820.h
new file mode 100644
index 0000000..d23c177
--- /dev/null
+++ b/tools/kvm/include/kvm/e820.h
@@ -0,0 +1,12 @@
+#ifndef KVM_E820_H
+#define KVM_E820_H
+
+#include <linux/types.h>
+
+#define SMAP    0x534d4150      /* ASCII "SMAP" */
+
+struct biosregs;
+
+void e820_query_map(struct biosregs *regs);
+
+#endif /* KVM_E820_H */
diff --git a/tools/kvm/include/kvm/framebuffer.h b/tools/kvm/include/kvm/framebuffer.h
new file mode 100644
index 0000000..b66d0ba
--- /dev/null
+++ b/tools/kvm/include/kvm/framebuffer.h
@@ -0,0 +1,34 @@
+#ifndef KVM__FRAMEBUFFER_H
+#define KVM__FRAMEBUFFER_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+struct framebuffer;
+
+struct fb_target_operations {
+	int (*start)(struct framebuffer *fb);
+};
+
+#define FB_MAX_TARGETS			2
+
+struct framebuffer {
+	struct list_head		node;
+
+	u32				width;
+	u32				height;
+	u8				depth;
+	char				*mem;
+	u64				mem_addr;
+	u64				mem_size;
+
+	unsigned long			nr_targets;
+	struct fb_target_operations	*targets[FB_MAX_TARGETS];
+};
+
+struct framebuffer *fb__register(struct framebuffer *fb);
+int fb__attach(struct framebuffer *fb, struct fb_target_operations *ops);
+int fb__start(void);
+void fb__stop(void);
+
+#endif /* KVM__FRAMEBUFFER_H */
diff --git a/tools/kvm/include/kvm/guest_compat.h b/tools/kvm/include/kvm/guest_compat.h
new file mode 100644
index 0000000..ae7abbd
--- /dev/null
+++ b/tools/kvm/include/kvm/guest_compat.h
@@ -0,0 +1,9 @@
+#ifndef KVM__GUEST_COMPAT_H
+#define KVM__GUEST_COMPAT_H
+
+int compat__print_all_messages(void);
+int compat__remove_message(int id);
+int compat__add_message(const char *title, const char *description);
+
+
+#endif
\ No newline at end of file
diff --git a/tools/kvm/include/kvm/i8042.h b/tools/kvm/include/kvm/i8042.h
new file mode 100644
index 0000000..13f18e2
--- /dev/null
+++ b/tools/kvm/include/kvm/i8042.h
@@ -0,0 +1,12 @@
+#ifndef KVM__PCKBD_H
+#define KVM__PCKBD_H
+
+#include <linux/types.h>
+
+struct kvm;
+
+void mouse_queue(u8 c);
+void kbd_queue(u8 c);
+void kbd__init(struct kvm *kvm);
+
+#endif
diff --git a/tools/kvm/include/kvm/ioeventfd.h b/tools/kvm/include/kvm/ioeventfd.h
new file mode 100644
index 0000000..3a95788
--- /dev/null
+++ b/tools/kvm/include/kvm/ioeventfd.h
@@ -0,0 +1,27 @@
+#ifndef KVM__IOEVENTFD_H
+#define KVM__IOEVENTFD_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <sys/eventfd.h>
+
+struct kvm;
+
+struct ioevent {
+	u64			io_addr;
+	u8			io_len;
+	void			(*fn)(struct kvm *kvm, void *ptr);
+	struct kvm		*fn_kvm;
+	void			*fn_ptr;
+	int			fd;
+	u64			datamatch;
+
+	struct list_head	list;
+};
+
+void ioeventfd__init(struct kvm *kvm);
+void ioeventfd__start(void);
+void ioeventfd__add_event(struct ioevent *ioevent);
+void ioeventfd__del_event(u64 addr, u64 datamatch);
+
+#endif
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
new file mode 100644
index 0000000..09bf876
--- /dev/null
+++ b/tools/kvm/include/kvm/ioport.h
@@ -0,0 +1,66 @@
+#ifndef KVM__IOPORT_H
+#define KVM__IOPORT_H
+
+#include "kvm/rbtree-interval.h"
+
+#include <stdbool.h>
+#include <limits.h>
+#include <asm/types.h>
+#include <linux/types.h>
+#include <linux/byteorder.h>
+
+/* some ports we reserve for own use */
+#define IOPORT_DBG			0xe0
+#define IOPORT_START			0x6200
+#define IOPORT_SIZE			0x400
+
+#define IOPORT_EMPTY			USHRT_MAX
+
+struct kvm;
+
+struct ioport {
+	struct rb_int_node		node;
+	struct ioport_operations	*ops;
+	void				*priv;
+};
+
+struct ioport_operations {
+	bool (*io_in)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
+	bool (*io_out)(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size);
+};
+
+void ioport__setup_arch(void);
+
+u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param);
+
+static inline u8 ioport__read8(u8 *data)
+{
+	return *data;
+}
+/* On BE platforms, PCI I/O is byteswapped, i.e. LE, so swap back. */
+static inline u16 ioport__read16(u16 *data)
+{
+	return le16_to_cpu(*data);
+}
+
+static inline u32 ioport__read32(u32 *data)
+{
+	return le32_to_cpu(*data);
+}
+
+static inline void ioport__write8(u8 *data, u8 value)
+{
+	*data		 = value;
+}
+
+static inline void ioport__write16(u16 *data, u16 value)
+{
+	*data		 = cpu_to_le16(value);
+}
+
+static inline void ioport__write32(u32 *data, u32 value)
+{
+	*data		 = cpu_to_le32(value);
+}
+
+#endif /* KVM__IOPORT_H */
diff --git a/tools/kvm/include/kvm/irq.h b/tools/kvm/include/kvm/irq.h
new file mode 100644
index 0000000..61f593d
--- /dev/null
+++ b/tools/kvm/include/kvm/irq.h
@@ -0,0 +1,31 @@
+#ifndef KVM__IRQ_H
+#define KVM__IRQ_H
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+#include <linux/msi.h>
+
+struct kvm;
+
+struct irq_line {
+	u8			line;
+	struct list_head	node;
+};
+
+struct pci_dev {
+	struct rb_node		node;
+	u32			id;
+	u8			pin;
+	struct list_head	lines;
+};
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line);
+
+struct rb_node *irq__get_pci_tree(void);
+
+void irq__init(struct kvm *kvm);
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-cmd.h b/tools/kvm/include/kvm/kvm-cmd.h
new file mode 100644
index 0000000..0a73bce
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-cmd.h
@@ -0,0 +1,17 @@
+#ifndef __KVM_CMD_H__
+#define __KVM_CMD_H__
+
+struct cmd_struct {
+	const char *cmd;
+	int (*fn)(int, const char **, const char *);
+	void (*help)(void);
+	int option;
+};
+
+extern struct cmd_struct kvm_commands[];
+struct cmd_struct *kvm_get_command(struct cmd_struct *command,
+                const char *cmd);
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
new file mode 100644
index 0000000..d4448f6
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-cpu.h
@@ -0,0 +1,24 @@
+#ifndef KVM__KVM_CPU_H
+#define KVM__KVM_CPU_H
+
+#include "kvm/kvm-cpu-arch.h"
+#include <stdbool.h>
+
+struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id);
+void kvm_cpu__delete(struct kvm_cpu *vcpu);
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu);
+void kvm_cpu__setup_cpuid(struct kvm_cpu *vcpu);
+void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu);
+void kvm_cpu__run(struct kvm_cpu *vcpu);
+void kvm_cpu__reboot(void);
+int kvm_cpu__start(struct kvm_cpu *cpu);
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
+
+int kvm_cpu__get_debug_fd(void);
+void kvm_cpu__set_debug_fd(int fd);
+void kvm_cpu__show_code(struct kvm_cpu *vcpu);
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu);
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu);
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu);
+
+#endif /* KVM__KVM_CPU_H */
diff --git a/tools/kvm/include/kvm/kvm-ipc.h b/tools/kvm/include/kvm/kvm-ipc.h
new file mode 100644
index 0000000..aefffa4
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm-ipc.h
@@ -0,0 +1,24 @@
+#ifndef KVM__IPC_H_
+#define KVM__IPC_H_
+
+#include <linux/types.h>
+
+enum {
+	KVM_IPC_BALLOON	= 1,
+	KVM_IPC_DEBUG	= 2,
+	KVM_IPC_STAT	= 3,
+	KVM_IPC_PAUSE	= 4,
+	KVM_IPC_RESUME	= 5,
+	KVM_IPC_STOP	= 6,
+	KVM_IPC_PID	= 7,
+	KVM_IPC_VMSTATE	= 8,
+};
+
+int kvm_ipc__register_handler(u32 type, void (*cb)(int fd, u32 type, u32 len, u8 *msg));
+int kvm_ipc__start(int sock);
+int kvm_ipc__stop(void);
+
+int kvm_ipc__send(int fd, u32 type);
+int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg);
+
+#endif
diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h
new file mode 100644
index 0000000..d48f2e2
--- /dev/null
+++ b/tools/kvm/include/kvm/kvm.h
@@ -0,0 +1,91 @@
+#ifndef KVM__KVM_H
+#define KVM__KVM_H
+
+#include "kvm/kvm-arch.h"
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+#include <signal.h>
+
+#define SIGKVMEXIT		(SIGRTMIN + 0)
+#define SIGKVMPAUSE		(SIGRTMIN + 1)
+
+#define KVM_PID_FILE_PATH	"/.kvm-tools/"
+#define HOME_DIR		getenv("HOME")
+#define KVM_BINARY_NAME		"lkvm"
+
+#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
+
+#define DEFINE_KVM_EXT(ext)		\
+	.name = #ext,			\
+	.code = ext
+
+enum {
+	KVM_VMSTATE_RUNNING,
+	KVM_VMSTATE_PAUSED,
+};
+
+struct kvm_ext {
+	const char *name;
+	int code;
+};
+
+void kvm__set_dir(const char *fmt, ...);
+const char *kvm__get_dir(void);
+
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name);
+int kvm__recommended_cpus(struct kvm *kvm);
+int kvm__max_cpus(struct kvm *kvm);
+void kvm__init_ram(struct kvm *kvm);
+void kvm__delete(struct kvm *kvm);
+bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
+			const char *initrd_filename, const char *kernel_cmdline, u16 vidmode);
+void kvm__start_timer(struct kvm *kvm);
+void kvm__stop_timer(struct kvm *kvm);
+void kvm__irq_line(struct kvm *kvm, int irq, int level);
+void kvm__irq_trigger(struct kvm *kvm, int irq);
+bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count);
+bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write);
+void kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr);
+bool kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
+			void (*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
+			void *ptr);
+bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+void kvm__pause(void);
+void kvm__continue(void);
+void kvm__notify_paused(void);
+int kvm__get_sock_by_instance(const char *name);
+int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
+void kvm__remove_socket(const char *name);
+
+void kvm__arch_set_cmdline(char *cmdline, bool video);
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size);
+void kvm__arch_delete_ram(struct kvm *kvm);
+int kvm__arch_setup_firmware(struct kvm *kvm);
+bool kvm__arch_cpu_supports_vm(void);
+void kvm__arch_periodic_poll(struct kvm *kvm);
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline);
+bool load_bzimage(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline, u16 vidmode);
+
+/*
+ * Debugging
+ */
+void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size);
+
+extern const char *kvm_exit_reasons[];
+
+static inline bool host_ptr_in_ram(struct kvm *kvm, void *p)
+{
+	return kvm->ram_start <= p && p < (kvm->ram_start + kvm->ram_size);
+}
+
+static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset)
+{
+	return kvm->ram_start + offset;
+}
+
+bool kvm__supports_extension(struct kvm *kvm, unsigned int extension);
+
+#endif /* KVM__KVM_H */
diff --git a/tools/kvm/include/kvm/mutex.h b/tools/kvm/include/kvm/mutex.h
new file mode 100644
index 0000000..3286cea
--- /dev/null
+++ b/tools/kvm/include/kvm/mutex.h
@@ -0,0 +1,33 @@
+#ifndef KVM__MUTEX_H
+#define KVM__MUTEX_H
+
+#include <pthread.h>
+
+#include "kvm/util.h"
+
+/*
+ * Kernel-alike mutex API - to make it easier for kernel developers
+ * to write user-space code! :-)
+ */
+
+#define DEFINE_MUTEX(mutex) pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
+
+static inline void mutex_init(pthread_mutex_t *mutex)
+{
+	if (pthread_mutex_init(mutex, NULL) != 0)
+		die("unexpected pthread_mutex_init() failure!");
+}
+
+static inline void mutex_lock(pthread_mutex_t *mutex)
+{
+	if (pthread_mutex_lock(mutex) != 0)
+		die("unexpected pthread_mutex_lock() failure!");
+}
+
+static inline void mutex_unlock(pthread_mutex_t *mutex)
+{
+	if (pthread_mutex_unlock(mutex) != 0)
+		die("unexpected pthread_mutex_unlock() failure!");
+}
+
+#endif /* KVM__MUTEX_H */
diff --git a/tools/kvm/include/kvm/parse-options.h b/tools/kvm/include/kvm/parse-options.h
new file mode 100644
index 0000000..7886ff7
--- /dev/null
+++ b/tools/kvm/include/kvm/parse-options.h
@@ -0,0 +1,214 @@
+#ifndef __PARSE_OPTIONS_H__
+#define __PARSE_OPTIONS_H__
+
+#include <inttypes.h>
+#include <kvm/util.h>
+
+enum parse_opt_type {
+	/* special types */
+	OPTION_END,
+	OPTION_ARGUMENT,
+	OPTION_GROUP,
+	/* options with no arguments */
+	OPTION_BIT,
+	OPTION_BOOLEAN,
+	OPTION_INCR,
+	OPTION_SET_UINT,
+	OPTION_SET_PTR,
+	/* options with arguments (usually) */
+	OPTION_STRING,
+	OPTION_INTEGER,
+	OPTION_LONG,
+	OPTION_CALLBACK,
+	OPTION_U64,
+	OPTION_UINTEGER,
+};
+
+enum parse_opt_flags {
+	PARSE_OPT_KEEP_DASHDASH = 1,
+	PARSE_OPT_STOP_AT_NON_OPTION = 2,
+	PARSE_OPT_KEEP_ARGV0 = 4,
+	PARSE_OPT_KEEP_UNKNOWN = 8,
+	PARSE_OPT_NO_INTERNAL_HELP = 16,
+};
+
+enum parse_opt_option_flags {
+	PARSE_OPT_OPTARG  = 1,
+	PARSE_OPT_NOARG   = 2,
+	PARSE_OPT_NONEG   = 4,
+	PARSE_OPT_HIDDEN  = 8,
+	PARSE_OPT_LASTARG_DEFAULT = 16,
+};
+
+struct option;
+typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
+/*
+ * `type`::
+ *   holds the type of the option, you must have an OPTION_END last in your
+ *   array.
+ *
+ * `short_name`::
+ *   the character to use as a short option name, '\0' if none.
+ *
+ * `long_name`::
+ *   the long option name, without the leading dashes, NULL if none.
+ *
+ * `value`::
+ *   stores pointers to the values to be filled.
+ *
+ * `argh`::
+ *   token to explain the kind of argument this option wants. Keep it
+ *   homogenous across the repository.
+ *
+ * `help`::
+ *   the short help associated to what the option does.
+ *   Must never be NULL (except for OPTION_END).
+ *   OPTION_GROUP uses this pointer to store the group header.
+ *
+ * `flags`::
+ *   mask of parse_opt_option_flags.
+ *   PARSE_OPT_OPTARG: says that the argument is optionnal (not for BOOLEANs)
+ *   PARSE_OPT_NOARG: says that this option takes no argument, for CALLBACKs
+ *   PARSE_OPT_NONEG: says that this option cannot be negated
+ *   PARSE_OPT_HIDDEN this option is skipped in the default usage, showed in
+ *                    the long one.
+ *
+ * `callback`::
+ *   pointer to the callback to use for OPTION_CALLBACK.
+ *
+ * `defval`::
+ *   default value to fill (*->value) with for PARSE_OPT_OPTARG.
+ *   OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
+ *   the value when met.
+ *   CALLBACKS can use it like they want.
+ */
+struct option {
+enum parse_opt_type type;
+int short_name;
+const char *long_name;
+void *value;
+const char *argh;
+const char *help;
+
+int flags;
+parse_opt_cb *callback;
+intptr_t defval;
+};
+
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+#define check_vtype(v, type) \
+	(BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v)
+
+#define OPT_INTEGER(s, l, v, h)             \
+{                                           \
+	.type = OPTION_INTEGER,             \
+	.short_name = (s),                  \
+	.long_name = (l),                   \
+	.value = check_vtype(v, int *),     \
+	.help = (h)                         \
+}
+
+#define OPT_U64(s, l, v, h)                 \
+{                                           \
+	.type = OPTION_U64,                 \
+	.short_name = (s),                  \
+	.long_name = (l),                   \
+	.value = check_vtype(v, u64 *),     \
+	.help = (h)                         \
+}
+
+#define OPT_STRING(s, l, v, a, h)           \
+{                                           \
+	.type = OPTION_STRING,              \
+	.short_name = (s),                  \
+	.long_name = (l),                   \
+	.value = check_vtype(v, const char **), (a), \
+	.help = (h)                         \
+}
+
+#define OPT_BOOLEAN(s, l, v, h)             \
+{                                           \
+	.type = OPTION_BOOLEAN,             \
+	.short_name = (s),                  \
+	.long_name = (l),                   \
+	.value = check_vtype(v, bool *),    \
+	.help = (h)                         \
+}
+
+#define OPT_INCR(s, l, v, h)                \
+{                                           \
+	.type = OPTION_INCR,	            \
+	.short_name = (s),                  \
+	.long_name = (l),                   \
+	.value = check_vtype(v, int *),     \
+	.help = (h)                         \
+}
+
+#define OPT_GROUP(h)                        \
+{                                           \
+	.type = OPTION_GROUP,               \
+	.help = (h)                         \
+}
+
+#define OPT_CALLBACK(s, l, v, a, h, f)      \
+{					    \
+	.type = OPTION_CALLBACK,	    \
+	.short_name = (s),		    \
+	.long_name = (l),		    \
+	.value = (v),			    \
+	(a),				    \
+	.help = (h),			    \
+	.callback = (f)			    \
+}
+
+#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
+{					    \
+	.type = OPTION_CALLBACK,	    \
+	.short_name = (s),		    \
+	.long_name = (l),		    \
+	.value = (v),			    \
+	(a),				    \
+	.help = (h),			    \
+	.callback = (f),		    \
+	.flags = PARSE_OPT_NOARG	    \
+}
+
+#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
+{					    \
+	.type = OPTION_CALLBACK,	    \
+	.short_name = (s),		    \
+	.long_name = (l),		    \
+	.value = (v), (a),		    \
+	.help = (h),			    \
+	.callback = (f),		    \
+	.defval = (intptr_t)d,		    \
+	.flags = PARSE_OPT_LASTARG_DEFAULT  \
+}
+
+#define OPT_END() { .type = OPTION_END }
+
+enum {
+	PARSE_OPT_HELP = -1,
+	PARSE_OPT_DONE,
+	PARSE_OPT_UNKNOWN,
+};
+
+/*
+ * It's okay for the caller to consume argv/argc in the usual way.
+ * Other fields of that structure are private to parse-options and should not
+ * be modified in any way.
+ **/
+struct parse_opt_ctx_t {
+	const char **argv;
+	const char **out;
+	int argc, cpidx;
+	const char *opt;
+	int flags;
+};
+
+/* global functions */
+void usage_with_options(const char * const *usagestr,
+		const struct option *opts) NORETURN;
+int parse_options(int argc, const char **argv, const struct option *options,
+		const char * const usagestr[], int flags);
+#endif
diff --git a/tools/kvm/include/kvm/pci-shmem.h b/tools/kvm/include/kvm/pci-shmem.h
new file mode 100644
index 0000000..599ab37
--- /dev/null
+++ b/tools/kvm/include/kvm/pci-shmem.h
@@ -0,0 +1,28 @@
+#ifndef KVM__PCI_SHMEM_H
+#define KVM__PCI_SHMEM_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+#define SHMEM_DEFAULT_SIZE (16 << MB_SHIFT)
+#define SHMEM_DEFAULT_ADDR (0xc8000000)
+#define SHMEM_DEFAULT_HANDLE "/kvm_shmem"
+
+struct kvm;
+struct shmem_info;
+
+struct shmem_info {
+	u64 phys_addr;
+	u64 size;
+	char *handle;
+	int create;
+};
+
+int pci_shmem__init(struct kvm *self);
+int pci_shmem__register_mem(struct shmem_info *si);
+
+int pci_shmem__get_local_irqfd(struct kvm *kvm);
+int pci_shmem__add_client(struct kvm *kvm, u32 id, int fd);
+int pci_shmem__remove_client(struct kvm *kvm, u32 id);
+
+#endif
diff --git a/tools/kvm/include/kvm/pci.h b/tools/kvm/include/kvm/pci.h
new file mode 100644
index 0000000..07b5403
--- /dev/null
+++ b/tools/kvm/include/kvm/pci.h
@@ -0,0 +1,94 @@
+#ifndef KVM__PCI_H
+#define KVM__PCI_H
+
+#include <linux/types.h>
+#include <linux/kvm.h>
+#include <linux/pci_regs.h>
+#include <linux/msi.h>
+#include <endian.h>
+
+#include "kvm/kvm.h"
+
+#define PCI_MAX_DEVICES			256
+/*
+ * PCI Configuration Mechanism #1 I/O ports. See Section 3.7.4.1.
+ * ("Configuration Mechanism #1") of the PCI Local Bus Specification 2.1 for
+ * details.
+ */
+#define PCI_CONFIG_ADDRESS	0xcf8
+#define PCI_CONFIG_DATA		0xcfc
+#define PCI_CONFIG_BUS_FORWARD	0xcfa
+#define PCI_IO_SIZE		0x100
+
+union pci_config_address {
+	struct {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+		unsigned	reg_offset	: 2;		/* 1  .. 0  */
+		unsigned	register_number	: 6;		/* 7  .. 2  */
+		unsigned	function_number	: 3;		/* 10 .. 8  */
+		unsigned	device_number	: 5;		/* 15 .. 11 */
+		unsigned	bus_number	: 8;		/* 23 .. 16 */
+		unsigned	reserved	: 7;		/* 30 .. 24 */
+		unsigned	enable_bit	: 1;		/* 31       */
+#else
+		unsigned	enable_bit	: 1;		/* 31       */
+		unsigned	reserved	: 7;		/* 30 .. 24 */
+		unsigned	bus_number	: 8;		/* 23 .. 16 */
+		unsigned	device_number	: 5;		/* 15 .. 11 */
+		unsigned	function_number	: 3;		/* 10 .. 8  */
+		unsigned	register_number	: 6;		/* 7  .. 2  */
+		unsigned	reg_offset	: 2;		/* 1  .. 0  */
+#endif
+	};
+	u32 w;
+};
+
+struct msix_table {
+	struct msi_msg msg;
+	u32 ctrl;
+};
+
+struct msix_cap {
+	u8 cap;
+	u8 next;
+	u16 ctrl;
+	u32 table_offset;
+	u32 pba_offset;
+};
+
+struct pci_device_header {
+	u16		vendor_id;
+	u16		device_id;
+	u16		command;
+	u16		status;
+	u8		revision_id;
+	u8		class[3];
+	u8		cacheline_size;
+	u8		latency_timer;
+	u8		header_type;
+	u8		bist;
+	u32		bar[6];
+	u32		card_bus;
+	u16		subsys_vendor_id;
+	u16		subsys_id;
+	u32		exp_rom_bar;
+	u8		capabilities;
+	u8		reserved1[3];
+	u32		reserved2;
+	u8		irq_line;
+	u8		irq_pin;
+	u8		min_gnt;
+	u8		max_lat;
+	struct msix_cap msix;
+	u8		empty[136]; /* Rest of PCI config space */
+	u32		bar_size[6];
+} __attribute__((packed));
+
+void pci__init(void);
+void pci__register(struct pci_device_header *dev, u8 dev_num);
+struct pci_device_header *pci__find_dev(u8 dev_num);
+u32 pci_get_io_space_block(u32 size);
+void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size);
+void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size);
+
+#endif /* KVM__PCI_H */
diff --git a/tools/kvm/include/kvm/qcow.h b/tools/kvm/include/kvm/qcow.h
new file mode 100644
index 0000000..e032a1e
--- /dev/null
+++ b/tools/kvm/include/kvm/qcow.h
@@ -0,0 +1,133 @@
+#ifndef KVM__QCOW_H
+#define KVM__QCOW_H
+
+#include "kvm/mutex.h"
+
+#include <linux/types.h>
+#include <stdbool.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+
+#define QCOW_MAGIC		(('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+
+#define QCOW1_VERSION		1
+#define QCOW2_VERSION		2
+
+#define QCOW1_OFLAG_COMPRESSED	(1ULL << 63)
+
+#define QCOW2_OFLAG_COPIED	(1ULL << 63)
+#define QCOW2_OFLAG_COMPRESSED	(1ULL << 62)
+
+#define QCOW2_OFLAGS_MASK	(QCOW2_OFLAG_COPIED|QCOW2_OFLAG_COMPRESSED)
+
+#define QCOW2_OFFSET_MASK	(~QCOW2_OFLAGS_MASK)
+
+#define MAX_CACHE_NODES         32
+
+struct qcow_l2_table {
+	u64				offset;
+	struct rb_node			node;
+	struct list_head		list;
+	u8				dirty;
+	u64				table[];
+};
+
+struct qcow_l1_table {
+	u32				table_size;
+	u64				*l1_table;
+
+	/* Level2 caching data structures */
+	struct rb_root			root;
+	struct list_head		lru_list;
+	int				nr_cached;
+};
+
+#define QCOW_REFCOUNT_BLOCK_SHIFT	1
+
+struct qcow_refcount_block {
+	u64				offset;
+	struct rb_node			node;
+	struct list_head		list;
+	u64				size;
+	u8				dirty;
+	u16				entries[];
+};
+
+struct qcow_refcount_table {
+	u32				rf_size;
+	u64				*rf_table;
+
+	/* Refcount block caching data structures */
+	struct rb_root			root;
+	struct list_head		lru_list;
+	int				nr_cached;
+};
+
+struct qcow_header {
+	u64				size;	/* in bytes */
+	u64				l1_table_offset;
+	u32				l1_size;
+	u8				cluster_bits;
+	u8				l2_bits;
+	u64				refcount_table_offset;
+	u32				refcount_table_size;
+};
+
+struct qcow {
+	pthread_mutex_t			mutex;
+	struct qcow_header		*header;
+	struct qcow_l1_table		table;
+	struct qcow_refcount_table	refcount_table;
+	int				fd;
+	int				csize_shift;
+	int				csize_mask;
+	u32				version;
+	u64				cluster_size;
+	u64				cluster_offset_mask;
+	u64				free_clust_idx;
+	void				*cluster_cache;
+	void				*cluster_data;
+	void				*copy_buff;
+};
+
+struct qcow1_header_disk {
+	u32				magic;
+	u32				version;
+
+	u64				backing_file_offset;
+	u32 				backing_file_size;
+	u32				mtime;
+
+	u64				size;	/* in bytes */
+
+	u8				cluster_bits;
+	u8				l2_bits;
+	u32				crypt_method;
+
+	u64				l1_table_offset;
+};
+
+struct qcow2_header_disk {
+	u32				magic;
+	u32				version;
+
+	u64				backing_file_offset;
+	u32				backing_file_size;
+
+	u32				cluster_bits;
+	u64				size;	/* in bytes */
+	u32				crypt_method;
+
+	u32				l1_size;
+	u64				l1_table_offset;
+
+	u64				refcount_table_offset;
+	u32				refcount_table_clusters;
+
+	u32				nb_snapshots;
+	u64				snapshots_offset;
+};
+
+struct disk_image *qcow_probe(int fd, bool readonly);
+
+#endif /* KVM__QCOW_H */
diff --git a/tools/kvm/include/kvm/rbtree-interval.h b/tools/kvm/include/kvm/rbtree-interval.h
new file mode 100644
index 0000000..a6688c4
--- /dev/null
+++ b/tools/kvm/include/kvm/rbtree-interval.h
@@ -0,0 +1,27 @@
+#ifndef KVM__INTERVAL_RBTREE_H
+#define KVM__INTERVAL_RBTREE_H
+
+#include <linux/rbtree.h>
+#include <linux/types.h>
+
+#define RB_INT_INIT(l, h) (struct rb_int_node){.low = l, .high = h}
+
+struct rb_int_node {
+	struct rb_node	node;
+	u64		low;
+	u64		high;
+
+	/* max_high will store the highest high of it's 2 children. */
+	u64		max_high;
+};
+
+/* Return the rb_int_node interval in which 'point' is located. */
+struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point);
+
+/* Return the rb_int_node in which start:len is located. */
+struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high);
+
+int rb_int_insert(struct rb_root *root, struct rb_int_node *data);
+void rb_int_erase(struct rb_root *root, struct rb_int_node *node);
+
+#endif
diff --git a/tools/kvm/include/kvm/read-write.h b/tools/kvm/include/kvm/read-write.h
new file mode 100644
index 0000000..67571f9
--- /dev/null
+++ b/tools/kvm/include/kvm/read-write.h
@@ -0,0 +1,43 @@
+#ifndef KVM_READ_WRITE_H
+#define KVM_READ_WRITE_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#ifdef CONFIG_HAS_AIO
+#include <libaio.h>
+#endif
+
+ssize_t xread(int fd, void *buf, size_t count);
+ssize_t xwrite(int fd, const void *buf, size_t count);
+
+ssize_t read_in_full(int fd, void *buf, size_t count);
+ssize_t write_in_full(int fd, const void *buf, size_t count);
+
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset);
+
+ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt);
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt);
+
+ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt);
+ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt);
+
+ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+
+ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+
+#ifdef CONFIG_HAS_AIO
+int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+		off_t offset, int ev, void *param);
+int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+		off_t offset, int ev, void *param);
+#endif
+
+#endif /* KVM_READ_WRITE_H */
diff --git a/tools/kvm/include/kvm/rtc.h b/tools/kvm/include/kvm/rtc.h
new file mode 100644
index 0000000..0b8d9f9
--- /dev/null
+++ b/tools/kvm/include/kvm/rtc.h
@@ -0,0 +1,6 @@
+#ifndef KVM__RTC_H
+#define KVM__RTC_H
+
+void rtc__init(void);
+
+#endif /* KVM__RTC_H */
diff --git a/tools/kvm/include/kvm/rwsem.h b/tools/kvm/include/kvm/rwsem.h
new file mode 100644
index 0000000..75a22f8
--- /dev/null
+++ b/tools/kvm/include/kvm/rwsem.h
@@ -0,0 +1,39 @@
+#ifndef KVM__RWSEM_H
+#define KVM__RWSEM_H
+
+#include <pthread.h>
+
+#include "kvm/util.h"
+
+/*
+ * Kernel-alike rwsem API - to make it easier for kernel developers
+ * to write user-space code! :-)
+ */
+
+#define DECLARE_RWSEM(sem) pthread_rwlock_t sem = PTHREAD_RWLOCK_INITIALIZER
+
+static inline void down_read(pthread_rwlock_t *rwsem)
+{
+	if (pthread_rwlock_rdlock(rwsem) != 0)
+		die("unexpected pthread_rwlock_rdlock() failure!");
+}
+
+static inline void down_write(pthread_rwlock_t *rwsem)
+{
+	if (pthread_rwlock_wrlock(rwsem) != 0)
+		die("unexpected pthread_rwlock_wrlock() failure!");
+}
+
+static inline void up_read(pthread_rwlock_t *rwsem)
+{
+	if (pthread_rwlock_unlock(rwsem) != 0)
+		die("unexpected pthread_rwlock_unlock() failure!");
+}
+
+static inline void up_write(pthread_rwlock_t *rwsem)
+{
+	if (pthread_rwlock_unlock(rwsem) != 0)
+		die("unexpected pthread_rwlock_unlock() failure!");
+}
+
+#endif /* KVM__RWSEM_H */
diff --git a/tools/kvm/include/kvm/sdl.h b/tools/kvm/include/kvm/sdl.h
new file mode 100644
index 0000000..a5aa411
--- /dev/null
+++ b/tools/kvm/include/kvm/sdl.h
@@ -0,0 +1,17 @@
+#ifndef KVM__SDL_H
+#define KVM__SDL_H
+
+#include "kvm/util.h"
+
+struct framebuffer;
+
+#ifdef CONFIG_HAS_SDL
+void sdl__init(struct framebuffer *fb);
+#else
+static inline void sdl__init(struct framebuffer *fb)
+{
+	die("SDL support not compiled in. (install the SDL-dev[el] package)");
+}
+#endif
+
+#endif /* KVM__SDL_H */
diff --git a/tools/kvm/include/kvm/segment.h b/tools/kvm/include/kvm/segment.h
new file mode 100644
index 0000000..9387a82
--- /dev/null
+++ b/tools/kvm/include/kvm/segment.h
@@ -0,0 +1,21 @@
+#ifndef KVM_SEGMENT_H
+#define KVM_SEGMENT_H
+
+#include <linux/types.h>
+
+static inline u32 segment_to_flat(u16 selector, u16 offset)
+{
+	return ((u32)selector << 4) + (u32) offset;
+}
+
+static inline u16 flat_to_seg16(u32 address)
+{
+	return address >> 4;
+}
+
+static inline u16 flat_to_off16(u32 address, u32 segment)
+{
+	return address - (segment << 4);
+}
+
+#endif /* KVM_SEGMENT_H */
diff --git a/tools/kvm/include/kvm/strbuf.h b/tools/kvm/include/kvm/strbuf.h
new file mode 100644
index 0000000..8fdef7e
--- /dev/null
+++ b/tools/kvm/include/kvm/strbuf.h
@@ -0,0 +1,19 @@
+#ifndef __STRBUF_H__
+#define __STRBUF_H__
+
+#include <sys/types.h>
+#include <string.h>
+
+int prefixcmp(const char *str, const char *prefix);
+
+extern size_t strlcat(char *dest, const char *src, size_t count);
+
+/* some inline functions */
+
+static inline const char *skip_prefix(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;
+}
+
+#endif
diff --git a/tools/kvm/include/kvm/symbol.h b/tools/kvm/include/kvm/symbol.h
new file mode 100644
index 0000000..5bc2221
--- /dev/null
+++ b/tools/kvm/include/kvm/symbol.h
@@ -0,0 +1,22 @@
+#ifndef KVM__SYMBOL_H
+#define KVM__SYMBOL_H
+
+#include <stddef.h>
+#include <string.h>
+
+struct kvm;
+
+#ifdef CONFIG_HAS_BFD
+void symbol__init(const char *vmlinux);
+char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size);
+#else
+static inline void symbol__init(const char *vmlinux) { }
+static inline char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
+{
+	char *s = strncpy(sym, "<unknown>", size);
+	sym[size - 1] = '\0';
+	return s;
+}
+#endif
+
+#endif /* KVM__SYMBOL_H */
diff --git a/tools/kvm/include/kvm/term.h b/tools/kvm/include/kvm/term.h
new file mode 100644
index 0000000..a6a9822
--- /dev/null
+++ b/tools/kvm/include/kvm/term.h
@@ -0,0 +1,20 @@
+#ifndef KVM__TERM_H
+#define KVM__TERM_H
+
+#include <sys/uio.h>
+#include <stdbool.h>
+
+#define CONSOLE_8250	1
+#define CONSOLE_VIRTIO	2
+#define CONSOLE_HV	3
+
+int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term);
+int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term);
+int term_putc(int who, char *addr, int cnt, int term);
+int term_getc(int who, int term);
+
+bool term_readable(int who, int term);
+void term_set_tty(int term);
+void term_init(void);
+
+#endif /* KVM__TERM_H */
diff --git a/tools/kvm/include/kvm/threadpool.h b/tools/kvm/include/kvm/threadpool.h
new file mode 100644
index 0000000..768239f
--- /dev/null
+++ b/tools/kvm/include/kvm/threadpool.h
@@ -0,0 +1,37 @@
+#ifndef KVM__THREADPOOL_H
+#define KVM__THREADPOOL_H
+
+#include "kvm/mutex.h"
+
+#include <linux/list.h>
+
+struct kvm;
+
+typedef void (*kvm_thread_callback_fn_t)(struct kvm *kvm, void *data);
+
+struct thread_pool__job {
+	kvm_thread_callback_fn_t	callback;
+	struct kvm			*kvm;
+	void				*data;
+
+	int				signalcount;
+	pthread_mutex_t			mutex;
+
+	struct list_head		queue;
+};
+
+static inline void thread_pool__init_job(struct thread_pool__job *job, struct kvm *kvm, kvm_thread_callback_fn_t callback, void *data)
+{
+	*job = (struct thread_pool__job) {
+		.kvm		= kvm,
+		.callback	= callback,
+		.data		= data,
+		.mutex		= PTHREAD_MUTEX_INITIALIZER,
+	};
+}
+
+int thread_pool__init(unsigned long thread_count);
+
+void thread_pool__do_job(struct thread_pool__job *job);
+
+#endif
diff --git a/tools/kvm/include/kvm/types.h b/tools/kvm/include/kvm/types.h
new file mode 100644
index 0000000..0cbc5fb
--- /dev/null
+++ b/tools/kvm/include/kvm/types.h
@@ -0,0 +1,7 @@
+#ifndef KVM_TYPES_H
+#define KVM_TYPES_H
+
+/* FIXME: include/linux/if_tun.h and include/linux/if_ether.h complains */
+#define __be16 u16
+
+#endif /* KVM_TYPES_H */
diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h
new file mode 100644
index 0000000..4497f6a
--- /dev/null
+++ b/tools/kvm/include/kvm/uip.h
@@ -0,0 +1,358 @@
+#ifndef KVM__UIP_H
+#define KVM__UIP_H
+
+#include "linux/types.h"
+#include "kvm/mutex.h"
+
+#include <netinet/in.h>
+#include <sys/uio.h>
+
+#define UIP_BUF_STATUS_FREE	0
+#define UIP_BUF_STATUS_INUSE	1
+#define UIP_BUF_STATUS_USED	2
+
+#define UIP_ETH_P_IP		0X0800
+#define UIP_ETH_P_ARP		0X0806
+
+#define UIP_IP_VER_4		0X40
+#define UIP_IP_HDR_LEN		0X05
+#define UIP_IP_TTL		0X40
+#define UIP_IP_P_UDP		0X11
+#define UIP_IP_P_TCP		0X06
+#define UIP_IP_P_ICMP		0X01
+
+#define UIP_TCP_HDR_LEN		0x50
+#define UIP_TCP_WIN_SIZE	14600
+#define UIP_TCP_FLAG_FIN	1
+#define UIP_TCP_FLAG_SYN	2
+#define UIP_TCP_FLAG_RST	4
+#define UIP_TCP_FLAG_PSH	8
+#define UIP_TCP_FLAG_ACK	16
+#define UIP_TCP_FLAG_URG	32
+
+#define UIP_BOOTP_VENDOR_SPECIFIC_LEN	64
+#define UIP_BOOTP_MAX_PAYLOAD_LEN	300
+#define UIP_DHCP_VENDOR_SPECIFIC_LEN	312
+#define UIP_DHCP_PORT_SERVER		67
+#define UIP_DHCP_PORT_CLIENT		68
+#define UIP_DHCP_MACPAD_LEN		10
+#define UIP_DHCP_HOSTNAME_LEN		64
+#define UIP_DHCP_FILENAME_LEN		128
+#define UIP_DHCP_MAGIC_COOKIE		0x63825363
+#define UIP_DHCP_MAGIC_COOKIE_LEN	4
+#define UIP_DHCP_LEASE_TIME		0x00003840
+#define UIP_DHCP_MAX_PAYLOAD_LEN	(UIP_BOOTP_MAX_PAYLOAD_LEN - UIP_BOOTP_VENDOR_SPECIFIC_LEN +  UIP_DHCP_VENDOR_SPECIFIC_LEN)
+#define UIP_DHCP_OPTION_LEN		(UIP_DHCP_VENDOR_SPECIFIC_LEN - UIP_DHCP_MAGIC_COOKIE_LEN)
+#define UIP_DHCP_DISCOVER		1
+#define UIP_DHCP_OFFER			2
+#define UIP_DHCP_REQUEST		3
+#define UIP_DHCP_ACK			5
+#define UIP_DHCP_MAX_DNS_SERVER_NR	3
+#define UIP_DHCP_MAX_DOMAIN_NAME_LEN	256
+#define UIP_DHCP_TAG_MSG_TYPE		53
+#define UIP_DHCP_TAG_MSG_TYPE_LEN	1
+#define UIP_DHCP_TAG_SERVER_ID		54
+#define UIP_DHCP_TAG_SERVER_ID_LEN	4
+#define UIP_DHCP_TAG_LEASE_TIME		51
+#define UIP_DHCP_TAG_LEASE_TIME_LEN	4
+#define UIP_DHCP_TAG_SUBMASK		1
+#define UIP_DHCP_TAG_SUBMASK_LEN	4
+#define UIP_DHCP_TAG_ROUTER		3
+#define UIP_DHCP_TAG_ROUTER_LEN		4
+#define UIP_DHCP_TAG_ROOT		17
+#define UIP_DHCP_TAG_ROOT_LEN		4
+#define UIP_DHCP_TAG_DNS_SERVER		6
+#define UIP_DHCP_TAG_DNS_SERVER_LEN	4
+#define UIP_DHCP_TAG_DOMAIN_NAME	15
+#define UIP_DHCP_TAG_END		255
+
+/*
+ * IP package maxium len == 64 KBytes
+ * IP header == 20 Bytes
+ * TCP header == 20 Bytes
+ * UDP header == 8 Bytes
+ */
+#define UIP_MAX_TCP_PAYLOAD	(64*1024 - 20 - 20 - 1)
+#define UIP_MAX_UDP_PAYLOAD	(64*1024 - 20 -  8 - 1)
+
+struct uip_eth_addr {
+	u8 addr[6];
+};
+
+struct uip_eth {
+	struct uip_eth_addr dst;
+	struct uip_eth_addr src;
+	u16 type;
+} __attribute__((packed));
+
+struct uip_arp {
+	struct uip_eth eth;
+	u16 hwtype;
+	u16 proto;
+	u8 hwlen;
+	u8 protolen;
+	u16 op;
+	struct uip_eth_addr smac;
+	u32 sip;
+	struct uip_eth_addr dmac;
+	u32 dip;
+} __attribute__((packed));
+
+struct uip_ip {
+	struct uip_eth eth;
+	u8 vhl;
+	u8 tos;
+	/*
+	 * len = IP hdr +  IP payload
+	 */
+	u16 len;
+	u16 id;
+	u16 flgfrag;
+	u8 ttl;
+	u8 proto;
+	u16 csum;
+	u32 sip;
+	u32 dip;
+} __attribute__((packed));
+
+struct uip_icmp {
+	struct uip_ip ip;
+	u8 type;
+	u8 code;
+	u16 csum;
+	u16 id;
+	u16 seq;
+} __attribute__((packed));
+
+struct uip_udp {
+	/*
+	 * FIXME: IP Options (IP hdr len > 20 bytes) are not supported
+	 */
+	struct uip_ip ip;
+	u16 sport;
+	u16 dport;
+	/*
+	 * len = UDP hdr +  UDP payload
+	 */
+	u16 len;
+	u16 csum;
+	u8 payload[0];
+} __attribute__((packed));
+
+struct uip_tcp {
+	/*
+	 * FIXME: IP Options (IP hdr len > 20 bytes) are not supported
+	 */
+	struct uip_ip ip;
+	u16 sport;
+	u16 dport;
+	u32 seq;
+	u32 ack;
+	u8  off;
+	u8  flg;
+	u16 win;
+	u16 csum;
+	u16 urgent;
+} __attribute__((packed));
+
+struct uip_pseudo_hdr {
+	u32 sip;
+	u32 dip;
+	u8 zero;
+	u8 proto;
+	u16 len;
+} __attribute__((packed));
+
+struct uip_dhcp {
+	struct uip_udp udp;
+	u8 msg_type;
+	u8 hardware_type;
+	u8 hardware_len;
+	u8 hops;
+	u32 id;
+	u16 time;
+	u16 flg;
+	u32 client_ip;
+	u32 your_ip;
+	u32 server_ip;
+	u32 agent_ip;
+	struct uip_eth_addr client_mac;
+	u8 pad[UIP_DHCP_MACPAD_LEN];
+	u8 server_hostname[UIP_DHCP_HOSTNAME_LEN];
+	u8 boot_filename[UIP_DHCP_FILENAME_LEN];
+	u32 magic_cookie;
+	u8 option[UIP_DHCP_OPTION_LEN];
+} __attribute__((packed));
+
+struct uip_info {
+	struct list_head udp_socket_head;
+	struct list_head tcp_socket_head;
+	pthread_mutex_t udp_socket_lock;
+	pthread_mutex_t tcp_socket_lock;
+	struct uip_eth_addr guest_mac;
+	struct uip_eth_addr host_mac;
+	pthread_cond_t buf_free_cond;
+	pthread_cond_t buf_used_cond;
+	struct list_head buf_head;
+	pthread_mutex_t buf_lock;
+	pthread_t udp_thread;
+	int udp_epollfd;
+	int buf_free_nr;
+	int buf_used_nr;
+	u32 guest_ip;
+	u32 guest_netmask;
+	u32 host_ip;
+	u32 dns_ip[UIP_DHCP_MAX_DNS_SERVER_NR];
+	char *domain_name;
+	u32 buf_nr;
+};
+
+struct uip_buf {
+	struct list_head list;
+	struct uip_info *info;
+	int vnet_len;
+	int eth_len;
+	int status;
+	char *vnet;
+	char *eth;
+	int id;
+};
+
+struct uip_udp_socket {
+	struct sockaddr_in addr;
+	struct list_head list;
+	pthread_mutex_t *lock;
+	u32 dport, sport;
+	u32 dip, sip;
+	int fd;
+};
+
+struct uip_tcp_socket {
+	struct sockaddr_in addr;
+	struct list_head list;
+	struct uip_info *info;
+	pthread_mutex_t *lock;
+	pthread_t thread;
+	u32 dport, sport;
+	u32 guest_acked;
+	/*
+	 * Initial Sequence Number
+	 */
+	u32 isn_server;
+	u32 isn_guest;
+	u32 ack_server;
+	u32 seq_server;
+	int write_done;
+	int read_done;
+	u32 dip, sip;
+	u8 *payload;
+	int fd;
+};
+
+struct uip_tx_arg {
+	struct virtio_net_hdr *vnet;
+	struct uip_info *info;
+	struct uip_eth *eth;
+	int vnet_len;
+	int eth_len;
+};
+
+static inline u16 uip_ip_hdrlen(struct uip_ip *ip)
+{
+	return (ip->vhl & 0x0f) * 4;
+}
+
+static inline u16 uip_ip_len(struct uip_ip *ip)
+{
+	return htons(ip->len);
+}
+
+static inline u16 uip_udp_hdrlen(struct uip_udp *udp)
+{
+	return 8;
+}
+
+static inline u16 uip_udp_len(struct uip_udp *udp)
+{
+	return ntohs(udp->len);
+}
+
+static inline u16 uip_tcp_hdrlen(struct uip_tcp *tcp)
+{
+	return (tcp->off >> 4) * 4;
+}
+
+static inline u16 uip_tcp_len(struct uip_tcp *tcp)
+{
+	struct uip_ip *ip;
+
+	ip = &tcp->ip;
+
+	return uip_ip_len(ip) - uip_ip_hdrlen(ip);
+}
+
+static inline u16 uip_tcp_payloadlen(struct uip_tcp *tcp)
+{
+	return uip_tcp_len(tcp) - uip_tcp_hdrlen(tcp);
+}
+
+static inline u8 *uip_tcp_payload(struct uip_tcp *tcp)
+{
+	return (u8 *)&tcp->sport + uip_tcp_hdrlen(tcp);
+}
+
+static inline bool uip_tcp_is_syn(struct uip_tcp *tcp)
+{
+	return (tcp->flg & UIP_TCP_FLAG_SYN) != 0;
+}
+
+static inline bool uip_tcp_is_fin(struct uip_tcp *tcp)
+{
+	return (tcp->flg & UIP_TCP_FLAG_FIN) != 0;
+}
+
+static inline u32 uip_tcp_isn(struct uip_tcp *tcp)
+{
+	return ntohl(tcp->seq);
+}
+
+static inline u32 uip_tcp_isn_alloc(void)
+{
+	/*
+	 * FIXME: should increase every 4ms
+	 */
+	return 10000000;
+}
+
+static inline u16 uip_eth_hdrlen(struct uip_eth *eth)
+{
+	return sizeof(*eth);
+}
+
+int uip_tx(struct iovec *iov, u16 out, struct uip_info *info);
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info);
+int uip_init(struct uip_info *info);
+
+int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4_udp(struct uip_tx_arg *arg);
+int uip_tx_do_ipv4(struct uip_tx_arg *arg);
+int uip_tx_do_arp(struct uip_tx_arg *arg);
+
+u16 uip_csum_icmp(struct uip_icmp *icmp);
+u16 uip_csum_udp(struct uip_udp *udp);
+u16 uip_csum_tcp(struct uip_tcp *tcp);
+u16 uip_csum_ip(struct uip_ip *ip);
+
+struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf);
+struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf);
+struct uip_buf *uip_buf_get_used(struct uip_info *info);
+struct uip_buf *uip_buf_get_free(struct uip_info *info);
+struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg);
+
+int uip_udp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 *payload, int payload_len);
+bool uip_udp_is_dhcp(struct uip_udp *udp);
+
+int uip_dhcp_get_dns(struct uip_info *info);
+#endif /* KVM__UIP_H */
diff --git a/tools/kvm/include/kvm/util.h b/tools/kvm/include/kvm/util.h
new file mode 100644
index 0000000..dabf544
--- /dev/null
+++ b/tools/kvm/include/kvm/util.h
@@ -0,0 +1,95 @@
+#include <linux/stringify.h>
+
+#ifndef KVM__UTIL_H
+#define KVM__UTIL_H
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/*
+ * Some bits are stolen from perf tool :)
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <linux/types.h>
+
+#ifdef __GNUC__
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#ifndef __attribute__
+#define __attribute__(x)
+#endif
+#endif
+
+extern bool do_debug_print;
+
+#define PROT_RW (PROT_READ|PROT_WRITE)
+#define MAP_ANON_NORESERVE (MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE)
+
+extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern void die_perror(const char *s) NORETURN;
+extern int pr_err(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void pr_warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void pr_info(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
+
+#define pr_debug(fmt, ...)						\
+	do {								\
+		if (do_debug_print)					\
+			pr_info("(%s) %s:%d: " fmt, __FILE__,		\
+				__func__, __LINE__, ##__VA_ARGS__);	\
+	} while (0)
+
+
+#define BUILD_BUG_ON(condition)	((void)sizeof(char[1 - 2*!!(condition)]))
+
+#ifndef BUG_ON_HANDLER
+# define BUG_ON_HANDLER(condition)					\
+	do {								\
+		if ((condition)) {					\
+			pr_err("BUG at %s:%d", __FILE__, __LINE__);	\
+			raise(SIGABRT);					\
+		}							\
+	} while (0)
+#endif
+
+#define BUG_ON(condition)	BUG_ON_HANDLER((condition))
+
+#define DIE_IF(cnd)						\
+do {								\
+	if (cnd)						\
+	die(" at (" __FILE__ ":" __stringify(__LINE__) "): "	\
+		__stringify(cnd) "\n");				\
+} while (0)
+
+#define WARN_ON(condition) ({					\
+	int __ret_warn_on = !!(condition);			\
+	if (__ret_warn_on)					\
+		pr_warning("(%s) %s:%d: failed condition: %s",	\
+				__FILE__, __func__, __LINE__,	\
+				__stringify(condition));	\
+	__ret_warn_on;						\
+})
+
+#define MSECS_TO_USECS(s) ((s) * 1000)
+
+/* Millisecond sleep */
+static inline void msleep(unsigned int msecs)
+{
+	usleep(MSECS_TO_USECS(msecs));
+}
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size);
+
+#endif /* KVM__UTIL_H */
diff --git a/tools/kvm/include/kvm/vesa.h b/tools/kvm/include/kvm/vesa.h
new file mode 100644
index 0000000..ac041d9
--- /dev/null
+++ b/tools/kvm/include/kvm/vesa.h
@@ -0,0 +1,18 @@
+#ifndef KVM__VESA_H
+#define KVM__VESA_H
+
+#include <linux/types.h>
+
+#define VESA_WIDTH	640
+#define VESA_HEIGHT	480
+
+#define VESA_MEM_ADDR	0xd0000000
+#define VESA_MEM_SIZE	(4*VESA_WIDTH*VESA_HEIGHT)
+#define VESA_BPP	32
+
+struct kvm;
+struct biosregs;
+
+struct framebuffer *vesa__init(struct kvm *self);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-9p.h b/tools/kvm/include/kvm/virtio-9p.h
new file mode 100644
index 0000000..ac3dc45
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-9p.h
@@ -0,0 +1,74 @@
+#ifndef KVM__VIRTIO_9P_H
+#define KVM__VIRTIO_9P_H
+#include "kvm/virtio.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/virtio-trans.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <linux/list.h>
+
+#define NUM_VIRT_QUEUES		1
+#define VIRTQUEUE_NUM		128
+#define	VIRTIO_P9_DEFAULT_TAG	"kvm_9p"
+#define VIRTIO_P9_HDR_LEN	(sizeof(u32)+sizeof(u8)+sizeof(u16))
+#define VIRTIO_P9_MAX_FID	256
+#define VIRTIO_P9_VERSION_DOTL	"9P2000.L"
+#define MAX_TAG_LEN		32
+
+struct p9_msg {
+	u32			size;
+	u8			cmd;
+	u16			tag;
+	u8			msg[0];
+} __attribute__((packed));
+
+struct p9_fid {
+	u32			fid;
+	u32			uid;
+	u8			is_dir;
+	char			abs_path[PATH_MAX];
+	char			*path;
+	DIR			*dir;
+	int			fd;
+};
+
+struct p9_dev_job {
+	struct virt_queue	*vq;
+	struct p9_dev		*p9dev;
+	struct thread_pool__job job_id;
+};
+
+struct p9_dev {
+	struct list_head	list;
+	struct virtio_trans	vtrans;
+
+	struct virtio_9p_config	*config;
+	u32			features;
+
+	/* virtio queue */
+	struct virt_queue	vqs[NUM_VIRT_QUEUES];
+	struct p9_dev_job	jobs[NUM_VIRT_QUEUES];
+	struct p9_fid		fids[VIRTIO_P9_MAX_FID];
+	char			root_dir[PATH_MAX];
+};
+
+struct p9_pdu {
+	u32			queue_head;
+	size_t			read_offset;
+	size_t			write_offset;
+	u16			out_iov_cnt;
+	u16			in_iov_cnt;
+	struct iovec		in_iov[VIRTQUEUE_NUM];
+	struct iovec		out_iov[VIRTQUEUE_NUM];
+};
+
+struct kvm;
+
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name);
+int virtio_9p__init(struct kvm *kvm);
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...);
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-balloon.h b/tools/kvm/include/kvm/virtio-balloon.h
new file mode 100644
index 0000000..eb49fd4
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-balloon.h
@@ -0,0 +1,8 @@
+#ifndef KVM__BLN_VIRTIO_H
+#define KVM__BLN_VIRTIO_H
+
+struct kvm;
+
+void virtio_bln__init(struct kvm *kvm);
+
+#endif /* KVM__BLN_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-blk.h b/tools/kvm/include/kvm/virtio-blk.h
new file mode 100644
index 0000000..63731a9
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-blk.h
@@ -0,0 +1,13 @@
+#ifndef KVM__BLK_VIRTIO_H
+#define KVM__BLK_VIRTIO_H
+
+#include "kvm/disk-image.h"
+
+struct kvm;
+
+void virtio_blk__init(struct kvm *kvm, struct disk_image *disk);
+void virtio_blk__init_all(struct kvm *kvm);
+void virtio_blk__delete_all(struct kvm *kvm);
+void virtio_blk_complete(void *param, long len);
+
+#endif /* KVM__BLK_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-console.h b/tools/kvm/include/kvm/virtio-console.h
new file mode 100644
index 0000000..50d8653
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-console.h
@@ -0,0 +1,9 @@
+#ifndef KVM__CONSOLE_VIRTIO_H
+#define KVM__CONSOLE_VIRTIO_H
+
+struct kvm;
+
+void virtio_console__init(struct kvm *kvm);
+void virtio_console__inject_interrupt(struct kvm *kvm);
+
+#endif /* KVM__CONSOLE_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-net.h b/tools/kvm/include/kvm/virtio-net.h
new file mode 100644
index 0000000..a3219b6
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-net.h
@@ -0,0 +1,23 @@
+#ifndef KVM__VIRTIO_NET_H
+#define KVM__VIRTIO_NET_H
+
+struct kvm;
+
+struct virtio_net_params {
+	const char *guest_ip;
+	const char *host_ip;
+	const char *script;
+	char guest_mac[6];
+	char host_mac[6];
+	struct kvm *kvm;
+	int mode;
+	int vhost;
+	int fd;
+};
+
+void virtio_net__init(const struct virtio_net_params *params);
+
+#define NET_MODE_USER	0
+#define NET_MODE_TAP	1
+
+#endif /* KVM__VIRTIO_NET_H */
diff --git a/tools/kvm/include/kvm/virtio-pci-dev.h b/tools/kvm/include/kvm/virtio-pci-dev.h
new file mode 100644
index 0000000..e692bdd
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-pci-dev.h
@@ -0,0 +1,37 @@
+#ifndef VIRTIO_PCI_DEV_H_
+#define VIRTIO_PCI_DEV_H_
+
+#include <linux/virtio_ids.h>
+
+/*
+ * Virtio PCI device constants and resources
+ * they do use (such as irqs and pins).
+ */
+
+#define PCI_DEVICE_ID_VIRTIO_NET		0x1000
+#define PCI_DEVICE_ID_VIRTIO_BLK		0x1001
+#define PCI_DEVICE_ID_VIRTIO_CONSOLE		0x1003
+#define PCI_DEVICE_ID_VIRTIO_RNG		0x1004
+#define PCI_DEVICE_ID_VIRTIO_BLN		0x1005
+#define PCI_DEVICE_ID_VIRTIO_P9			0x1009
+#define PCI_DEVICE_ID_VESA			0x2000
+#define PCI_DEVICE_ID_PCI_SHMEM			0x0001
+
+#define PCI_VENDOR_ID_REDHAT_QUMRANET		0x1af4
+#define PCI_VENDOR_ID_PCI_SHMEM			0x0001
+#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET	0x1af4
+
+#define PCI_SUBSYSTEM_ID_VESA			0x0004
+#define PCI_SUBSYSTEM_ID_PCI_SHMEM		0x0001
+
+#define PCI_CLASS_BLK				0x018000
+#define PCI_CLASS_NET				0x020000
+#define PCI_CLASS_CONSOLE			0x078000
+/*
+ * 0xFF Device does not fit in any defined classes
+ */
+#define PCI_CLASS_RNG				0xff0000
+#define PCI_CLASS_BLN				0xff0000
+#define PCI_CLASS_P9				0xff0000
+
+#endif /* VIRTIO_PCI_DEV_H_ */
diff --git a/tools/kvm/include/kvm/virtio-pci.h b/tools/kvm/include/kvm/virtio-pci.h
new file mode 100644
index 0000000..73f7486
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-pci.h
@@ -0,0 +1,48 @@
+#ifndef KVM__VIRTIO_PCI_H
+#define KVM__VIRTIO_PCI_H
+
+#include "kvm/pci.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/types.h>
+
+#define VIRTIO_PCI_MAX_VQ	3
+#define VIRTIO_PCI_MAX_CONFIG	1
+
+struct kvm;
+
+struct virtio_pci_ioevent_param {
+	struct virtio_trans	*vtrans;
+	u32			vq;
+};
+
+struct virtio_pci {
+	struct pci_device_header pci_hdr;
+	void			*dev;
+
+	u16			base_addr;
+	u8			status;
+	u8			isr;
+
+	/* MSI-X */
+	u16			config_vector;
+	u32			config_gsi;
+	u32			vq_vector[VIRTIO_PCI_MAX_VQ];
+	u32			gsis[VIRTIO_PCI_MAX_VQ];
+	u32			msix_io_block;
+	u64			msix_pba;
+	struct msix_table	msix_table[VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG];
+
+	/* virtio queue */
+	u16			queue_selector;
+	struct virtio_pci_ioevent_param ioeventfds[VIRTIO_PCI_MAX_VQ];
+};
+
+int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
+			int device_id, int subsys_id, int class);
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq);
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_trans *vtrans);
+
+struct virtio_trans_ops *virtio_pci__get_trans_ops(void);
+
+#endif
diff --git a/tools/kvm/include/kvm/virtio-rng.h b/tools/kvm/include/kvm/virtio-rng.h
new file mode 100644
index 0000000..c0a413b
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-rng.h
@@ -0,0 +1,9 @@
+#ifndef KVM__RNG_VIRTIO_H
+#define KVM__RNG_VIRTIO_H
+
+struct kvm;
+
+void virtio_rng__init(struct kvm *kvm);
+void virtio_rng__delete_all(struct kvm *kvm);
+
+#endif /* KVM__RNG_VIRTIO_H */
diff --git a/tools/kvm/include/kvm/virtio-trans.h b/tools/kvm/include/kvm/virtio-trans.h
new file mode 100644
index 0000000..e7c186e
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio-trans.h
@@ -0,0 +1,43 @@
+#ifndef KVM__VIRTIO_TRANS_H
+#define KVM__VIRTIO_TRANS_H
+
+#include "kvm/kvm.h"
+
+enum virtio_trans_type {
+	VIRTIO_PCI,
+};
+
+struct virtio_trans;
+
+struct virtio_ops {
+	void (*set_config)(struct kvm *kvm, void *dev, u8 data, u32 offset);
+	u8 (*get_config)(struct kvm *kvm, void *dev, u32 offset);
+
+	u32 (*get_host_features)(struct kvm *kvm, void *dev);
+	void (*set_guest_features)(struct kvm *kvm, void *dev, u32 features);
+
+	int (*init_vq)(struct kvm *kvm, void *dev, u32 vq, u32 pfn);
+	int (*notify_vq)(struct kvm *kvm, void *dev, u32 vq);
+	int (*get_pfn_vq)(struct kvm *kvm, void *dev, u32 vq);
+	int (*get_size_vq)(struct kvm *kvm, void *dev, u32 vq);
+	void (*notify_vq_gsi)(struct kvm *kvm, void *dev, u32 vq, u32 gsi);
+	void (*notify_vq_eventfd)(struct kvm *kvm, void *dev, u32 vq, u32 efd);
+};
+
+struct virtio_trans_ops {
+	int (*init)(struct kvm *kvm, struct virtio_trans *vtrans, void *dev, int device_id,
+			int subsys_id, int class);
+	int (*signal_vq)(struct kvm *kvm, struct virtio_trans *virtio_trans, u32 queueid);
+	int (*signal_config)(struct kvm *kvm, struct virtio_trans *virtio_trans);
+};
+
+struct virtio_trans {
+	void			*virtio;
+	enum virtio_trans_type	type;
+	struct virtio_trans_ops	*trans_ops;
+	struct virtio_ops	*virtio_ops;
+};
+
+int virtio_trans_init(struct virtio_trans *vtrans, enum virtio_trans_type type);
+
+#endif
\ No newline at end of file
diff --git a/tools/kvm/include/kvm/virtio.h b/tools/kvm/include/kvm/virtio.h
new file mode 100644
index 0000000..610f4d0
--- /dev/null
+++ b/tools/kvm/include/kvm/virtio.h
@@ -0,0 +1,67 @@
+#ifndef KVM__VIRTIO_H
+#define KVM__VIRTIO_H
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_pci.h>
+
+#include <linux/types.h>
+#include <sys/uio.h>
+
+#include "kvm/kvm.h"
+
+#define VIRTIO_IRQ_LOW		0
+#define VIRTIO_IRQ_HIGH		1
+
+#define VIRTIO_PCI_O_CONFIG	0
+#define VIRTIO_PCI_O_MSIX	1
+
+struct virt_queue {
+	struct vring	vring;
+	u32		pfn;
+	/* The last_avail_idx field is an index to ->ring of struct vring_avail.
+	   It's where we assume the next request index is at.  */
+	u16		last_avail_idx;
+	u16		last_used_signalled;
+};
+
+static inline u16 virt_queue__pop(struct virt_queue *queue)
+{
+	return queue->vring.avail->ring[queue->last_avail_idx++ % queue->vring.num];
+}
+
+static inline struct vring_desc *virt_queue__get_desc(struct virt_queue *queue, u16 desc_ndx)
+{
+	return &queue->vring.desc[desc_ndx];
+}
+
+static inline bool virt_queue__available(struct virt_queue *vq)
+{
+	if (!vq->vring.avail)
+		return 0;
+
+	vring_avail_event(&vq->vring) = vq->last_avail_idx;
+	return vq->vring.avail->idx !=  vq->last_avail_idx;
+}
+
+/*
+ * Warning: on 32-bit hosts, shifting pfn left may cause a truncation of pfn values
+ * higher than 4GB - thus, pointing to the wrong area in guest virtual memory space
+ * and breaking the virt queue which owns this pfn.
+ */
+static inline void *guest_pfn_to_host(struct kvm *kvm, u32 pfn)
+{
+	return guest_flat_to_host(kvm, (unsigned long)pfn << VIRTIO_PCI_QUEUE_ADDR_SHIFT);
+}
+
+
+struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len);
+
+bool virtio_queue__should_signal(struct virt_queue *vq);
+u16 virt_queue__get_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm);
+u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, u16 head, struct kvm *kvm);
+u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
+			      struct iovec in_iov[], struct iovec out_iov[],
+			      u16 *in, u16 *out);
+int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off);
+
+#endif /* KVM__VIRTIO_H */
diff --git a/tools/kvm/include/kvm/vnc.h b/tools/kvm/include/kvm/vnc.h
new file mode 100644
index 0000000..da2f635
--- /dev/null
+++ b/tools/kvm/include/kvm/vnc.h
@@ -0,0 +1,14 @@
+#ifndef KVM__VNC_H
+#define KVM__VNC_H
+
+struct framebuffer;
+
+#ifdef CONFIG_HAS_VNCSERVER
+void vnc__init(struct framebuffer *fb);
+#else
+static inline void vnc__init(struct framebuffer *fb)
+{
+}
+#endif
+
+#endif /* KVM__VNC_H */
diff --git a/tools/kvm/include/linux/bitops.h b/tools/kvm/include/linux/bitops.h
new file mode 100644
index 0000000..56448b7
--- /dev/null
+++ b/tools/kvm/include/linux/bitops.h
@@ -0,0 +1,33 @@
+#ifndef _KVM_LINUX_BITOPS_H_
+#define _KVM_LINUX_BITOPS_H_
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <asm/hweight.h>
+
+#define BITS_PER_LONG __WORDSIZE
+#define BITS_PER_BYTE           8
+#define BITS_TO_LONGS(nr)       DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+
+static inline void set_bit(int nr, unsigned long *addr)
+{
+	addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
+}
+
+static inline void clear_bit(int nr, unsigned long *addr)
+{
+	addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
+}
+
+static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
+{
+	return ((1UL << (nr % BITS_PER_LONG)) &
+		(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
+}
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+	return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+#endif
diff --git a/tools/kvm/include/linux/byteorder.h b/tools/kvm/include/linux/byteorder.h
new file mode 100644
index 0000000..c490de8
--- /dev/null
+++ b/tools/kvm/include/linux/byteorder.h
@@ -0,0 +1,7 @@
+#ifndef __BYTE_ORDER_H__
+#define __BYTE_ORDER_H__
+
+#include <asm/byteorder.h>
+#include <linux/byteorder/generic.h>
+
+#endif
diff --git a/tools/kvm/include/linux/compiler.h b/tools/kvm/include/linux/compiler.h
new file mode 100644
index 0000000..b9c5346
--- /dev/null
+++ b/tools/kvm/include/linux/compiler.h
@@ -0,0 +1,19 @@
+#ifndef _PERF_LINUX_COMPILER_H_
+#define _PERF_LINUX_COMPILER_H_
+
+#ifndef __always_inline
+#define __always_inline	inline
+#endif
+#define __user
+
+#ifndef __attribute_const__
+#define __attribute_const__
+#endif
+
+#define __used		__attribute__((__unused__))
+#define __iomem
+#define __force
+#define __must_check
+#define unlikely
+
+#endif
diff --git a/tools/kvm/include/linux/kernel.h b/tools/kvm/include/linux/kernel.h
new file mode 100644
index 0000000..d2ec4a3
--- /dev/null
+++ b/tools/kvm/include/linux/kernel.h
@@ -0,0 +1,39 @@
+
+#ifndef KVM__LINUX_KERNEL_H_
+#define KVM__LINUX_KERNEL_H_
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+#define ALIGN(x,a)		__ALIGN_MASK(x,(typeof(x))(a)-1)
+#define __ALIGN_MASK(x,mask)	(((x)+(mask))&~(mask))
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef container_of
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:	the pointer to the member.
+ * @type:	the type of the container struct this is embedded in.
+ * @member:	the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({			\
+	const typeof(((type *)0)->member) * __mptr = (ptr);	\
+	(type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define min(x, y) ({				\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	(void) (&_min1 == &_min2);		\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#endif
diff --git a/tools/kvm/include/linux/module.h b/tools/kvm/include/linux/module.h
new file mode 100644
index 0000000..0e4c6a3
--- /dev/null
+++ b/tools/kvm/include/linux/module.h
@@ -0,0 +1,6 @@
+#ifndef KVM__LINUX_MODULE_H
+#define KVM__LINUX_MODULE_H
+
+#define EXPORT_SYMBOL(name)
+
+#endif
diff --git a/tools/kvm/include/linux/prefetch.h b/tools/kvm/include/linux/prefetch.h
new file mode 100644
index 0000000..62f6788
--- /dev/null
+++ b/tools/kvm/include/linux/prefetch.h
@@ -0,0 +1,6 @@
+#ifndef KVM__LINUX_PREFETCH_H
+#define KVM__LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/kvm/include/linux/types.h b/tools/kvm/include/linux/types.h
new file mode 100644
index 0000000..5e20f10
--- /dev/null
+++ b/tools/kvm/include/linux/types.h
@@ -0,0 +1,51 @@
+#ifndef LINUX_TYPES_H
+#define LINUX_TYPES_H
+
+#include <kvm/compiler.h>
+#define __SANE_USERSPACE_TYPES__	/* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8  u8;
+typedef __s8  s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#endif /* LINUX_TYPES_H */
diff --git a/tools/kvm/ioeventfd.c b/tools/kvm/ioeventfd.c
new file mode 100644
index 0000000..1d6a7ac
--- /dev/null
+++ b/tools/kvm/ioeventfd.c
@@ -0,0 +1,142 @@
+#include <sys/epoll.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <linux/kernel.h>
+#include <linux/kvm.h>
+#include <linux/types.h>
+
+#include "kvm/ioeventfd.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#define IOEVENTFD_MAX_EVENTS	20
+
+static struct	epoll_event events[IOEVENTFD_MAX_EVENTS];
+static int	epoll_fd;
+static LIST_HEAD(used_ioevents);
+static bool	ioeventfd_avail;
+
+void ioeventfd__init(struct kvm *kvm)
+{
+	ioeventfd_avail = kvm__supports_extension(kvm, KVM_CAP_IOEVENTFD);
+	if (!ioeventfd_avail)
+		return;
+
+	epoll_fd = epoll_create(IOEVENTFD_MAX_EVENTS);
+	if (epoll_fd < 0)
+		die("Failed creating epoll fd");
+}
+
+void ioeventfd__add_event(struct ioevent *ioevent)
+{
+	struct kvm_ioeventfd kvm_ioevent;
+	struct epoll_event epoll_event;
+	struct ioevent *new_ioevent;
+	int event;
+
+	if (!ioeventfd_avail)
+		return;
+
+	new_ioevent = malloc(sizeof(*new_ioevent));
+	if (new_ioevent == NULL)
+		die("Failed allocating memory for new ioevent");
+
+	*new_ioevent = *ioevent;
+	event = new_ioevent->fd;
+
+	kvm_ioevent = (struct kvm_ioeventfd) {
+		.addr			= ioevent->io_addr,
+		.len			= ioevent->io_len,
+		.datamatch		= ioevent->datamatch,
+		.fd			= event,
+		.flags			= KVM_IOEVENTFD_FLAG_PIO | KVM_IOEVENTFD_FLAG_DATAMATCH,
+	};
+
+	if (ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent) != 0)
+		die("Failed creating new ioeventfd");
+
+	epoll_event = (struct epoll_event) {
+		.events			= EPOLLIN,
+		.data.ptr		= new_ioevent,
+	};
+
+	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event, &epoll_event) != 0)
+		die("Failed assigning new event to the epoll fd");
+
+	list_add_tail(&new_ioevent->list, &used_ioevents);
+}
+
+void ioeventfd__del_event(u64 addr, u64 datamatch)
+{
+	struct kvm_ioeventfd kvm_ioevent;
+	struct ioevent *ioevent;
+	u8 found = 0;
+
+	if (!ioeventfd_avail)
+		return;
+
+	list_for_each_entry(ioevent, &used_ioevents, list) {
+		if (ioevent->io_addr == addr) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found == 0 || ioevent == NULL)
+		return;
+
+	kvm_ioevent = (struct kvm_ioeventfd) {
+		.addr			= ioevent->io_addr,
+		.len			= ioevent->io_len,
+		.datamatch		= ioevent->datamatch,
+		.flags			= KVM_IOEVENTFD_FLAG_PIO
+					| KVM_IOEVENTFD_FLAG_DEASSIGN
+					| KVM_IOEVENTFD_FLAG_DATAMATCH,
+	};
+
+	ioctl(ioevent->fn_kvm->vm_fd, KVM_IOEVENTFD, &kvm_ioevent);
+
+	epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ioevent->fd, NULL);
+
+	list_del(&ioevent->list);
+
+	close(ioevent->fd);
+	free(ioevent);
+}
+
+static void *ioeventfd__thread(void *param)
+{
+	for (;;) {
+		int nfds, i;
+
+		nfds = epoll_wait(epoll_fd, events, IOEVENTFD_MAX_EVENTS, -1);
+		for (i = 0; i < nfds; i++) {
+			u64 tmp;
+			struct ioevent *ioevent;
+
+			ioevent = events[i].data.ptr;
+
+			if (read(ioevent->fd, &tmp, sizeof(tmp)) < 0)
+				die("Failed reading event");
+
+			ioevent->fn(ioevent->fn_kvm, ioevent->fn_ptr);
+		}
+	}
+
+	return NULL;
+}
+
+void ioeventfd__start(void)
+{
+	pthread_t thread;
+
+	if (!ioeventfd_avail)
+		return;
+
+	if (pthread_create(&thread, NULL, ioeventfd__thread, NULL) != 0)
+		die("Failed starting ioeventfd thread");
+}
diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c
new file mode 100644
index 0000000..5a5a331
--- /dev/null
+++ b/tools/kvm/ioport.c
@@ -0,0 +1,134 @@
+#include "kvm/ioport.h"
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+#include "kvm/brlock.h"
+#include "kvm/rbtree-interval.h"
+#include "kvm/mutex.h"
+
+#include <linux/kvm.h>	/* for KVM_EXIT_* */
+#include <linux/types.h>
+
+#include <stdbool.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define ioport_node(n) rb_entry(n, struct ioport, node)
+
+DEFINE_MUTEX(ioport_mutex);
+
+static u16			free_io_port_idx; /* protected by ioport_mutex */
+
+static struct rb_root		ioport_tree = RB_ROOT;
+bool				ioport_debug;
+
+static u16 ioport__find_free_port(void)
+{
+	u16 free_port;
+
+	mutex_lock(&ioport_mutex);
+	free_port = IOPORT_START + free_io_port_idx * IOPORT_SIZE;
+	free_io_port_idx++;
+	mutex_unlock(&ioport_mutex);
+
+	return free_port;
+}
+
+static struct ioport *ioport_search(struct rb_root *root, u64 addr)
+{
+	struct rb_int_node *node;
+
+	node = rb_int_search_single(root, addr);
+	if (node == NULL)
+		return NULL;
+
+	return ioport_node(node);
+}
+
+static int ioport_insert(struct rb_root *root, struct ioport *data)
+{
+	return rb_int_insert(root, &data->node);
+}
+
+u16 ioport__register(u16 port, struct ioport_operations *ops, int count, void *param)
+{
+	struct ioport *entry;
+
+	br_write_lock();
+	if (port == IOPORT_EMPTY)
+		port = ioport__find_free_port();
+
+	entry = ioport_search(&ioport_tree, port);
+	if (entry) {
+		pr_warning("ioport re-registered: %x", port);
+		rb_int_erase(&ioport_tree, &entry->node);
+	}
+
+	entry = malloc(sizeof(*entry));
+	if (entry == NULL)
+		die("Failed allocating new ioport entry");
+
+	*entry = (struct ioport) {
+		.node	= RB_INT_INIT(port, port + count),
+		.ops	= ops,
+		.priv	= param,
+	};
+
+	ioport_insert(&ioport_tree, entry);
+
+	br_write_unlock();
+
+	return port;
+}
+
+static const char *to_direction(int direction)
+{
+	if (direction == KVM_EXIT_IO_IN)
+		return "IN";
+	else
+		return "OUT";
+}
+
+static void ioport_error(u16 port, void *data, int direction, int size, u32 count)
+{
+	fprintf(stderr, "IO error: %s port=%x, size=%d, count=%u\n", to_direction(direction), port, size, count);
+}
+
+bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+	struct ioport_operations *ops;
+	bool ret = false;
+	struct ioport *entry;
+	void *ptr = data;
+
+	br_read_lock();
+	entry = ioport_search(&ioport_tree, port);
+	if (!entry)
+		goto error;
+
+	ops	= entry->ops;
+
+	while (count--) {
+		if (direction == KVM_EXIT_IO_IN && ops->io_in)
+				ret = ops->io_in(entry, kvm, port, ptr, size);
+		else if (ops->io_out)
+				ret = ops->io_out(entry, kvm, port, ptr, size);
+
+		ptr += size;
+	}
+
+	br_read_unlock();
+
+	if (!ret)
+		goto error;
+
+	return true;
+error:
+	br_read_unlock();
+
+	if (ioport_debug)
+		ioport_error(port, data, direction, size, count);
+
+	return !ioport_debug;
+}
diff --git a/tools/kvm/kvm-cmd.c b/tools/kvm/kvm-cmd.c
new file mode 100644
index 0000000..2520b08
--- /dev/null
+++ b/tools/kvm/kvm-cmd.c
@@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* user defined header files */
+#include "kvm/builtin-debug.h"
+#include "kvm/builtin-pause.h"
+#include "kvm/builtin-resume.h"
+#include "kvm/builtin-balloon.h"
+#include "kvm/builtin-list.h"
+#include "kvm/builtin-version.h"
+#include "kvm/builtin-setup.h"
+#include "kvm/builtin-stop.h"
+#include "kvm/builtin-stat.h"
+#include "kvm/builtin-help.h"
+#include "kvm/builtin-sandbox.h"
+#include "kvm/kvm-cmd.h"
+#include "kvm/builtin-run.h"
+#include "kvm/util.h"
+
+struct cmd_struct kvm_commands[] = {
+	{ "pause",	kvm_cmd_pause,		kvm_pause_help,		0 },
+	{ "resume",	kvm_cmd_resume,		kvm_resume_help,	0 },
+	{ "debug",	kvm_cmd_debug,		kvm_debug_help,		0 },
+	{ "balloon",	kvm_cmd_balloon,	kvm_balloon_help,	0 },
+	{ "list",	kvm_cmd_list,		kvm_list_help,		0 },
+	{ "version",	kvm_cmd_version,	NULL,			0 },
+	{ "--version",	kvm_cmd_version,	NULL,			0 },
+	{ "stop",	kvm_cmd_stop,		kvm_stop_help,		0 },
+	{ "stat",	kvm_cmd_stat,		kvm_stat_help,		0 },
+	{ "help",	kvm_cmd_help,		NULL,			0 },
+	{ "setup",	kvm_cmd_setup,		kvm_setup_help,		0 },
+	{ "run",	kvm_cmd_run,		kvm_run_help,		0 },
+	{ "sandbox",	kvm_cmd_sandbox,	kvm_run_help,		0 },
+	{ NULL,		NULL,			NULL,			0 },
+};
+
+/*
+ * kvm_get_command: Searches the command in an array of the commands and
+ * returns a pointer to cmd_struct if a match is found.
+ *
+ * Input parameters:
+ * command: Array of possible commands. The last entry in the array must be
+ *          NULL.
+ * cmd: A string command to search in the array
+ *
+ * Return Value:
+ * NULL: If the cmd is not matched with any of the command in the command array
+ * p: Pointer to cmd_struct of the matching command
+ */
+struct cmd_struct *kvm_get_command(struct cmd_struct *command,
+		const char *cmd)
+{
+	struct cmd_struct *p = command;
+
+	while (p->cmd) {
+		if (!strcmp(p->cmd, cmd))
+			return p;
+		p++;
+	}
+	return NULL;
+}
+
+int handle_command(struct cmd_struct *command, int argc, const char **argv)
+{
+	struct cmd_struct *p;
+	const char *prefix = NULL;
+	int ret = 0;
+
+	if (!argv || !*argv) {
+		p = kvm_get_command(command, "help");
+		BUG_ON(!p);
+		return p->fn(argc, argv, prefix);
+	}
+
+	p = kvm_get_command(command, argv[0]);
+	if (!p) {
+		p = kvm_get_command(command, "help");
+		BUG_ON(!p);
+		p->fn(0, NULL, prefix);
+		return EINVAL;
+	}
+
+	ret = p->fn(argc - 1, &argv[1], prefix);
+	if (ret < 0) {
+		if (errno == EPERM)
+			die("Permission error - are you root?");
+	}
+
+	return ret;
+}
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
new file mode 100644
index 0000000..12791dd
--- /dev/null
+++ b/tools/kvm/kvm-cpu.c
@@ -0,0 +1,175 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+extern struct kvm_cpu **kvm_cpus;
+extern __thread struct kvm_cpu *current_kvm_cpu;
+
+void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
+{
+	struct kvm_guest_debug debug = {
+		.control	= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_SINGLESTEP,
+	};
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_GUEST_DEBUG, &debug) < 0)
+		pr_warning("KVM_SET_GUEST_DEBUG failed");
+}
+
+void kvm_cpu__run(struct kvm_cpu *vcpu)
+{
+	int err;
+
+	if (!vcpu->is_running)
+		return;
+
+	err = ioctl(vcpu->vcpu_fd, KVM_RUN, 0);
+	if (err < 0 && (errno != EINTR && errno != EAGAIN))
+		die_perror("KVM_RUN failed");
+}
+
+static void kvm_cpu_signal_handler(int signum)
+{
+	if (signum == SIGKVMEXIT) {
+		if (current_kvm_cpu && current_kvm_cpu->is_running) {
+			current_kvm_cpu->is_running = false;
+			kvm__continue();
+		}
+	} else if (signum == SIGKVMPAUSE) {
+		current_kvm_cpu->paused = 1;
+	}
+}
+
+static void kvm_cpu__handle_coalesced_mmio(struct kvm_cpu *cpu)
+{
+	if (cpu->ring) {
+		while (cpu->ring->first != cpu->ring->last) {
+			struct kvm_coalesced_mmio *m;
+			m = &cpu->ring->coalesced_mmio[cpu->ring->first];
+			kvm_cpu__emulate_mmio(cpu->kvm,
+					      m->phys_addr,
+					      m->data,
+					      m->len,
+					      1);
+			cpu->ring->first = (cpu->ring->first + 1) % KVM_COALESCED_MMIO_MAX;
+		}
+	}
+}
+
+void kvm_cpu__reboot(void)
+{
+	int i;
+
+	/* The kvm_cpus array contains a null pointer in the last location */
+	for (i = 0; ; i++) {
+		if (kvm_cpus[i])
+			pthread_kill(kvm_cpus[i]->thread, SIGKVMEXIT);
+		else
+			break;
+	}
+}
+
+int kvm_cpu__start(struct kvm_cpu *cpu)
+{
+	sigset_t sigset;
+
+	sigemptyset(&sigset);
+	sigaddset(&sigset, SIGALRM);
+
+	pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+	signal(SIGKVMEXIT, kvm_cpu_signal_handler);
+	signal(SIGKVMPAUSE, kvm_cpu_signal_handler);
+
+	kvm_cpu__reset_vcpu(cpu);
+
+	if (cpu->kvm->single_step)
+		kvm_cpu__enable_singlestep(cpu);
+
+	while (cpu->is_running) {
+		if (cpu->paused) {
+			kvm__notify_paused();
+			cpu->paused = 0;
+		}
+
+		if (cpu->needs_nmi) {
+			kvm_cpu__arch_nmi(cpu);
+			cpu->needs_nmi = 0;
+		}
+
+		kvm_cpu__run(cpu);
+
+		switch (cpu->kvm_run->exit_reason) {
+		case KVM_EXIT_UNKNOWN:
+			break;
+		case KVM_EXIT_DEBUG:
+			kvm_cpu__show_registers(cpu);
+			kvm_cpu__show_code(cpu);
+			break;
+		case KVM_EXIT_IO: {
+			bool ret;
+
+			ret = kvm_cpu__emulate_io(cpu->kvm,
+						  cpu->kvm_run->io.port,
+						  (u8 *)cpu->kvm_run +
+						  cpu->kvm_run->io.data_offset,
+						  cpu->kvm_run->io.direction,
+						  cpu->kvm_run->io.size,
+						  cpu->kvm_run->io.count);
+
+			if (!ret)
+				goto panic_kvm;
+			break;
+		}
+		case KVM_EXIT_MMIO: {
+			bool ret;
+
+			/*
+			 * If we had MMIO exit, coalesced ring should be processed
+			 * *before* processing the exit itself
+			 */
+			kvm_cpu__handle_coalesced_mmio(cpu);
+
+			ret = kvm_cpu__emulate_mmio(cpu->kvm,
+						    cpu->kvm_run->mmio.phys_addr,
+						    cpu->kvm_run->mmio.data,
+						    cpu->kvm_run->mmio.len,
+						    cpu->kvm_run->mmio.is_write);
+
+			if (!ret)
+				goto panic_kvm;
+			break;
+		}
+		case KVM_EXIT_INTR:
+			if (cpu->is_running)
+				break;
+			goto exit_kvm;
+		case KVM_EXIT_SHUTDOWN:
+			goto exit_kvm;
+		default: {
+			bool ret;
+
+			ret = kvm_cpu__handle_exit(cpu);
+			if (!ret)
+				goto panic_kvm;
+			break;
+		}
+		}
+		kvm_cpu__handle_coalesced_mmio(cpu);
+	}
+
+exit_kvm:
+	return 0;
+
+panic_kvm:
+	return 1;
+}
diff --git a/tools/kvm/kvm-ipc.c b/tools/kvm/kvm-ipc.c
new file mode 100644
index 0000000..6a0bd21
--- /dev/null
+++ b/tools/kvm/kvm-ipc.c
@@ -0,0 +1,205 @@
+#include "kvm/kvm-ipc.h"
+#include "kvm/rwsem.h"
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+
+#include <sys/epoll.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/eventfd.h>
+
+struct kvm_ipc_head {
+	u32 type;
+	u32 len;
+};
+
+#define KVM_IPC_MAX_MSGS 16
+
+static void (*msgs[KVM_IPC_MAX_MSGS])(int fd, u32 type, u32 len, u8 *msg);
+static DECLARE_RWSEM(msgs_rwlock);
+static int epoll_fd, server_fd, stop_fd;
+static pthread_t thread;
+
+int kvm_ipc__register_handler(u32 type, void (*cb)(int fd, u32 type, u32 len, u8 *msg))
+{
+	if (type >= KVM_IPC_MAX_MSGS)
+		return -ENOSPC;
+
+	down_write(&msgs_rwlock);
+	msgs[type] = cb;
+	up_write(&msgs_rwlock);
+
+	return 0;
+}
+
+int kvm_ipc__send(int fd, u32 type)
+{
+	struct kvm_ipc_head head = {.type = type, .len = 0,};
+
+	if (write_in_full(fd, &head, sizeof(head)) < 0)
+		return -1;
+
+	return 0;
+}
+
+int kvm_ipc__send_msg(int fd, u32 type, u32 len, u8 *msg)
+{
+	struct kvm_ipc_head head = {.type = type, .len = len,};
+
+	if (write_in_full(fd, &head, sizeof(head)) < 0)
+		return -1;
+
+	if (write_in_full(fd, msg, len) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int kvm_ipc__handle(int fd, u32 type, u32 len, u8 *data)
+{
+	void (*cb)(int fd, u32 type, u32 len, u8 *msg);
+
+	if (type >= KVM_IPC_MAX_MSGS)
+		return -ENOSPC;
+
+	down_read(&msgs_rwlock);
+	cb = msgs[type];
+	up_read(&msgs_rwlock);
+
+	if (cb == NULL) {
+		pr_warning("No device handles type %u\n", type);
+		return -ENODEV;
+	}
+
+	cb(fd, type, len, data);
+
+	return 0;
+}
+
+static int kvm_ipc__new_conn(int fd)
+{
+	int client;
+	struct epoll_event ev;
+
+	client = accept(fd, NULL, NULL);
+	if (client < 0)
+		return -1;
+
+	ev.events = EPOLLIN | EPOLLRDHUP;
+	ev.data.fd = client;
+	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client, &ev) < 0) {
+		close(client);
+		return -1;
+	}
+
+	return client;
+}
+
+static void kvm_ipc__close_conn(int fd)
+{
+	epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
+	close(fd);
+}
+
+static int kvm_ipc__receive(int fd)
+{
+	struct kvm_ipc_head head;
+	u8 *msg = NULL;
+	u32 n;
+
+	n = read(fd, &head, sizeof(head));
+	if (n != sizeof(head))
+		goto done;
+
+	msg = malloc(head.len);
+	if (msg == NULL)
+		goto done;
+
+	n = read_in_full(fd, msg, head.len);
+	if (n != head.len)
+		goto done;
+
+	kvm_ipc__handle(fd, head.type, head.len, msg);
+
+	return 0;
+
+done:
+	free(msg);
+	return -1;
+}
+
+static void *kvm_ipc__thread(void *param)
+{
+	struct epoll_event event;
+
+	for (;;) {
+		int nfds;
+
+		nfds = epoll_wait(epoll_fd, &event, 1, -1);
+		if (nfds > 0) {
+			int fd = event.data.fd;
+
+			if (fd == stop_fd && event.events & EPOLLIN) {
+				break;
+			} else if (fd == server_fd) {
+				int client, r;
+
+				client = kvm_ipc__new_conn(fd);
+				/*
+				 * Handle multiple IPC cmd at a time
+				 */
+				do {
+					r = kvm_ipc__receive(client);
+				} while	(r == 0);
+
+			} else if (event.events && (EPOLLERR | EPOLLRDHUP | EPOLLHUP)) {
+				kvm_ipc__close_conn(fd);
+			} else {
+				kvm_ipc__receive(fd);
+			}
+		}
+	}
+
+	return NULL;
+}
+
+int kvm_ipc__start(int sock)
+{
+	struct epoll_event ev = {0};
+
+	server_fd = sock;
+
+	epoll_fd = epoll_create(KVM_IPC_MAX_MSGS);
+
+	ev.events = EPOLLIN | EPOLLET;
+	ev.data.fd = sock;
+	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev) < 0)
+		die("Failed starting IPC thread");
+
+	stop_fd = eventfd(0, 0);
+	ev.events = EPOLLIN | EPOLLET;
+	ev.data.fd = stop_fd;
+	if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, stop_fd, &ev) < 0)
+		die("Failed adding stop event to epoll");
+
+	if (pthread_create(&thread, NULL, kvm_ipc__thread, NULL) != 0)
+		die("Failed starting IPC thread");
+
+	return 0;
+}
+
+int kvm_ipc__stop(void)
+{
+	u64 val = 1;
+	int ret;
+
+	ret = write(stop_fd, &val, sizeof(val));
+	if (ret < 0)
+		return ret;
+
+	close(server_fd);
+	close(epoll_fd);
+
+	return ret;
+}
diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
new file mode 100644
index 0000000..a45f041
--- /dev/null
+++ b/tools/kvm/kvm.c
@@ -0,0 +1,533 @@
+#include "kvm/kvm.h"
+#include "kvm/read-write.h"
+#include "kvm/util.h"
+#include "kvm/mutex.h"
+#include "kvm/kvm-cpu.h"
+#include "kvm/kvm-ipc.h"
+
+#include <linux/kvm.h>
+
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/eventfd.h>
+#include <asm/unistd.h>
+#include <dirent.h>
+
+#define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason
+
+const char *kvm_exit_reasons[] = {
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_UNKNOWN),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_EXCEPTION),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_IO),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_HYPERCALL),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_DEBUG),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_HLT),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_MMIO),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_IRQ_WINDOW_OPEN),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_SHUTDOWN),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_FAIL_ENTRY),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTR),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_SET_TPR),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_TPR_ACCESS),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_SIEIC),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_S390_RESET),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
+#ifdef CONFIG_PPC64
+	DEFINE_KVM_EXIT_REASON(KVM_EXIT_PAPR_HCALL),
+#endif
+};
+
+extern struct kvm *kvm;
+extern struct kvm_cpu **kvm_cpus;
+static int pause_event;
+static DEFINE_MUTEX(pause_lock);
+extern struct kvm_ext kvm_req_ext[];
+
+static char kvm_dir[PATH_MAX];
+
+static void set_dir(const char *fmt, va_list args)
+{
+	char tmp[PATH_MAX];
+
+	vsnprintf(tmp, sizeof(tmp), fmt, args);
+
+	mkdir(tmp, 0777);
+
+	if (!realpath(tmp, kvm_dir))
+		die("Unable to set KVM tool directory");
+
+	strcat(kvm_dir, "/");
+}
+
+void kvm__set_dir(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	set_dir(fmt, args);
+	va_end(args);
+}
+
+const char *kvm__get_dir(void)
+{
+	return kvm_dir;
+}
+
+bool kvm__supports_extension(struct kvm *kvm, unsigned int extension)
+{
+	int ret;
+
+	ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, extension);
+	if (ret < 0)
+		return false;
+
+	return ret;
+}
+
+static int kvm__check_extensions(struct kvm *kvm)
+{
+	unsigned int i;
+
+	for (i = 0; ; i++) {
+		if (!kvm_req_ext[i].name)
+			break;
+		if (!kvm__supports_extension(kvm, kvm_req_ext[i].code)) {
+			pr_err("Unsuppored KVM extension detected: %s",
+				kvm_req_ext[i].name);
+			return (int)-i;
+		}
+	}
+
+	return 0;
+}
+
+static struct kvm *kvm__new(void)
+{
+	struct kvm *kvm = calloc(1, sizeof *kvm);
+
+	if (!kvm)
+		die("out of memory");
+
+	return kvm;
+}
+
+#define KVM_SOCK_SUFFIX		".sock"
+#define KVM_SOCK_SUFFIX_LEN	((ssize_t)sizeof(KVM_SOCK_SUFFIX) - 1)
+
+static int kvm__create_socket(struct kvm *kvm)
+{
+	char full_name[PATH_MAX];
+	unsigned int s;
+	struct sockaddr_un local;
+	int len, r;
+
+	if (!kvm->name)
+		return -1;
+
+	sprintf(full_name, "%s/%s%s", kvm__get_dir(), kvm->name,
+			KVM_SOCK_SUFFIX);
+	if (access(full_name, F_OK) == 0)
+		die("Socket file %s already exist", full_name);
+
+	s = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (s < 0)
+		return s;
+	local.sun_family = AF_UNIX;
+	strcpy(local.sun_path, full_name);
+	len = strlen(local.sun_path) + sizeof(local.sun_family);
+	r = bind(s, (struct sockaddr *)&local, len);
+	if (r < 0)
+		goto fail;
+
+	r = listen(s, 5);
+	if (r < 0)
+		goto fail;
+
+	return s;
+
+fail:
+	close(s);
+	return -1;
+}
+
+void kvm__remove_socket(const char *name)
+{
+	char full_name[PATH_MAX];
+
+	sprintf(full_name, "%s/%s%s", kvm__get_dir(), name, KVM_SOCK_SUFFIX);
+	unlink(full_name);
+}
+
+int kvm__get_sock_by_instance(const char *name)
+{
+	int s, len, r;
+	char sock_file[PATH_MAX];
+	struct sockaddr_un local;
+
+	sprintf(sock_file, "%s/%s%s", kvm__get_dir(), name, KVM_SOCK_SUFFIX);
+	s = socket(AF_UNIX, SOCK_STREAM, 0);
+
+	local.sun_family = AF_UNIX;
+	strcpy(local.sun_path, sock_file);
+	len = strlen(local.sun_path) + sizeof(local.sun_family);
+
+	r = connect(s, &local, len);
+	if (r < 0 && errno == ECONNREFUSED) {
+		/* Tell the user clean ghost socket file */
+		pr_err("\"%s\" could be a ghost socket file, please remove it",
+				sock_file);
+		return -1;
+	} else if (r < 0) {
+		die("Failed connecting to instance");
+	}
+
+	return s;
+}
+
+int kvm__enumerate_instances(int (*callback)(const char *name, int fd))
+{
+	int sock;
+	DIR *dir;
+	struct dirent entry, *result;
+	int ret = 0;
+
+	dir = opendir(kvm__get_dir());
+	if (!dir)
+		return -1;
+
+	for (;;) {
+		readdir_r(dir, &entry, &result);
+		if (result == NULL)
+			break;
+		if (entry.d_type == DT_SOCK) {
+			ssize_t name_len = strlen(entry.d_name);
+			char *p;
+
+			if (name_len <= KVM_SOCK_SUFFIX_LEN)
+				continue;
+
+			p = &entry.d_name[name_len - KVM_SOCK_SUFFIX_LEN];
+			if (memcmp(KVM_SOCK_SUFFIX, p, KVM_SOCK_SUFFIX_LEN))
+				continue;
+
+			*p = 0;
+			sock = kvm__get_sock_by_instance(entry.d_name);
+			if (sock < 0)
+				continue;
+			ret = callback(entry.d_name, sock);
+			close(sock);
+			if (ret < 0)
+				break;
+		}
+	}
+
+	closedir(dir);
+
+	return ret;
+}
+
+void kvm__delete(struct kvm *kvm)
+{
+	kvm__stop_timer(kvm);
+
+	kvm__arch_delete_ram(kvm);
+	kvm_ipc__stop();
+	kvm__remove_socket(kvm->name);
+	free(kvm);
+}
+
+/*
+ * Note: KVM_SET_USER_MEMORY_REGION assumes that we don't pass overlapping
+ * memory regions to it. Therefore, be careful if you use this function for
+ * registering memory regions for emulating hardware.
+ */
+void kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void *userspace_addr)
+{
+	struct kvm_userspace_memory_region mem;
+	int ret;
+
+	mem = (struct kvm_userspace_memory_region) {
+		.slot			= kvm->mem_slots++,
+		.guest_phys_addr	= guest_phys,
+		.memory_size		= size,
+		.userspace_addr		= (unsigned long)userspace_addr,
+	};
+
+	ret = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
+	if (ret < 0)
+		die_perror("KVM_SET_USER_MEMORY_REGION ioctl");
+}
+
+int kvm__recommended_cpus(struct kvm *kvm)
+{
+	int ret;
+
+	ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_NR_VCPUS);
+	if (ret <= 0)
+		/*
+		 * api.txt states that if KVM_CAP_NR_VCPUS does not exist,
+		 * assume 4.
+		 */
+		return 4;
+
+	return ret;
+}
+
+static void kvm__pid(int fd, u32 type, u32 len, u8 *msg)
+{
+	pid_t pid = getpid();
+	int r = 0;
+
+	if (type == KVM_IPC_PID)
+		r = write(fd, &pid, sizeof(pid));
+
+	if (r < 0)
+		pr_warning("Failed sending PID");
+}
+
+/*
+ * The following hack should be removed once 'x86: Raise the hard
+ * VCPU count limit' makes it's way into the mainline.
+ */
+#ifndef KVM_CAP_MAX_VCPUS
+#define KVM_CAP_MAX_VCPUS 66
+#endif
+
+int kvm__max_cpus(struct kvm *kvm)
+{
+	int ret;
+
+	ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_MAX_VCPUS);
+	if (ret <= 0)
+		ret = kvm__recommended_cpus(kvm);
+
+	return ret;
+}
+
+struct kvm *kvm__init(const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
+{
+	struct kvm *kvm;
+	int ret;
+
+	if (!kvm__arch_cpu_supports_vm())
+		die("Your CPU does not support hardware virtualization");
+
+	kvm = kvm__new();
+
+	kvm->sys_fd = open(kvm_dev, O_RDWR);
+	if (kvm->sys_fd < 0) {
+		if (errno == ENOENT)
+			die("'%s' not found. Please make sure your kernel has CONFIG_KVM enabled and that the KVM modules are loaded.", kvm_dev);
+		if (errno == ENODEV)
+			die("'%s' KVM driver not available.\n  # (If the KVM module is loaded then 'dmesg' may offer further clues about the failure.)", kvm_dev);
+
+		fprintf(stderr, "  Fatal, could not open %s: ", kvm_dev);
+		perror(NULL);
+		exit(1);
+	}
+
+	ret = ioctl(kvm->sys_fd, KVM_GET_API_VERSION, 0);
+	if (ret != KVM_API_VERSION)
+		die_perror("KVM_API_VERSION ioctl");
+
+	kvm->vm_fd = ioctl(kvm->sys_fd, KVM_CREATE_VM, 0);
+	if (kvm->vm_fd < 0)
+		die_perror("KVM_CREATE_VM ioctl");
+
+	if (kvm__check_extensions(kvm))
+		die("A required KVM extention is not supported by OS");
+
+	kvm__arch_init(kvm, hugetlbfs_path, ram_size);
+
+	kvm->name = name;
+
+	kvm_ipc__start(kvm__create_socket(kvm));
+	kvm_ipc__register_handler(KVM_IPC_PID, kvm__pid);
+	return kvm;
+}
+
+/* RFC 1952 */
+#define GZIP_ID1		0x1f
+#define GZIP_ID2		0x8b
+#define CPIO_MAGIC		"0707"
+/* initrd may be gzipped, or a plain cpio */
+static bool initrd_check(int fd)
+{
+	unsigned char id[4];
+
+	if (read_in_full(fd, id, ARRAY_SIZE(id)) < 0)
+		return false;
+
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		die_perror("lseek");
+
+	return (id[0] == GZIP_ID1 && id[1] == GZIP_ID2) ||
+		!memcmp(id, CPIO_MAGIC, 4);
+}
+
+bool kvm__load_kernel(struct kvm *kvm, const char *kernel_filename,
+		const char *initrd_filename, const char *kernel_cmdline, u16 vidmode)
+{
+	bool ret;
+	int fd_kernel = -1, fd_initrd = -1;
+
+	fd_kernel = open(kernel_filename, O_RDONLY);
+	if (fd_kernel < 0)
+		die("Unable to open kernel %s", kernel_filename);
+
+	if (initrd_filename) {
+		fd_initrd = open(initrd_filename, O_RDONLY);
+		if (fd_initrd < 0)
+			die("Unable to open initrd %s", initrd_filename);
+
+		if (!initrd_check(fd_initrd))
+			die("%s is not an initrd", initrd_filename);
+	}
+
+	ret = load_bzimage(kvm, fd_kernel, fd_initrd, kernel_cmdline, vidmode);
+
+	if (ret)
+		goto found_kernel;
+
+	pr_warning("%s is not a bzImage. Trying to load it as a flat binary...", kernel_filename);
+
+	ret = load_flat_binary(kvm, fd_kernel, fd_initrd, kernel_cmdline);
+
+	if (ret)
+		goto found_kernel;
+
+	if (initrd_filename)
+		close(fd_initrd);
+	close(fd_kernel);
+
+	die("%s is not a valid bzImage or flat binary", kernel_filename);
+
+found_kernel:
+	if (initrd_filename)
+		close(fd_initrd);
+	close(fd_kernel);
+
+	return ret;
+}
+
+#define TIMER_INTERVAL_NS 1000000	/* 1 msec */
+
+/*
+ * This function sets up a timer that's used to inject interrupts from the
+ * userspace hypervisor into the guest at periodical intervals. Please note
+ * that clock interrupt, for example, is not handled here.
+ */
+void kvm__start_timer(struct kvm *kvm)
+{
+	struct itimerspec its;
+	struct sigevent sev;
+
+	memset(&sev, 0, sizeof(struct sigevent));
+	sev.sigev_value.sival_int	= 0;
+	sev.sigev_notify		= SIGEV_THREAD_ID;
+	sev.sigev_signo			= SIGALRM;
+	sev._sigev_un._tid		= syscall(__NR_gettid);
+
+	if (timer_create(CLOCK_REALTIME, &sev, &kvm->timerid) < 0)
+		die("timer_create()");
+
+	its.it_value.tv_sec		= TIMER_INTERVAL_NS / 1000000000;
+	its.it_value.tv_nsec		= TIMER_INTERVAL_NS % 1000000000;
+	its.it_interval.tv_sec		= its.it_value.tv_sec;
+	its.it_interval.tv_nsec		= its.it_value.tv_nsec;
+
+	if (timer_settime(kvm->timerid, 0, &its, NULL) < 0)
+		die("timer_settime()");
+}
+
+void kvm__stop_timer(struct kvm *kvm)
+{
+	if (kvm->timerid)
+		if (timer_delete(kvm->timerid) < 0)
+			die("timer_delete()");
+
+	kvm->timerid = 0;
+}
+
+void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size)
+{
+	unsigned char *p;
+	unsigned long n;
+
+	size &= ~7; /* mod 8 */
+	if (!size)
+		return;
+
+	p = guest_flat_to_host(kvm, addr);
+
+	for (n = 0; n < size; n += 8) {
+		if (!host_ptr_in_ram(kvm, p + n))
+			break;
+
+		printf("  0x%08lx: %02x %02x %02x %02x  %02x %02x %02x %02x\n",
+			addr + n, p[n + 0], p[n + 1], p[n + 2], p[n + 3],
+				  p[n + 4], p[n + 5], p[n + 6], p[n + 7]);
+	}
+}
+
+void kvm__pause(void)
+{
+	int i, paused_vcpus = 0;
+
+	/* Check if the guest is running */
+	if (!kvm_cpus[0] || kvm_cpus[0]->thread == 0)
+		return;
+
+	mutex_lock(&pause_lock);
+
+	pause_event = eventfd(0, 0);
+	if (pause_event < 0)
+		die("Failed creating pause notification event");
+	for (i = 0; i < kvm->nrcpus; i++)
+		pthread_kill(kvm_cpus[i]->thread, SIGKVMPAUSE);
+
+	while (paused_vcpus < kvm->nrcpus) {
+		u64 cur_read;
+
+		if (read(pause_event, &cur_read, sizeof(cur_read)) < 0)
+			die("Failed reading pause event");
+		paused_vcpus += cur_read;
+	}
+	close(pause_event);
+}
+
+void kvm__continue(void)
+{
+	/* Check if the guest is running */
+	if (!kvm_cpus[0] || kvm_cpus[0]->thread == 0)
+		return;
+
+	mutex_unlock(&pause_lock);
+}
+
+void kvm__notify_paused(void)
+{
+	u64 p = 1;
+
+	if (write(pause_event, &p, sizeof(p)) < 0)
+		die("Failed notifying of paused VCPU.");
+
+	mutex_lock(&pause_lock);
+	mutex_unlock(&pause_lock);
+}
diff --git a/tools/kvm/main.c b/tools/kvm/main.c
new file mode 100644
index 0000000..05bc82c
--- /dev/null
+++ b/tools/kvm/main.c
@@ -0,0 +1,19 @@
+#include "kvm/kvm.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* user defined header files */
+#include <kvm/kvm-cmd.h>
+
+static int handle_kvm_command(int argc, char **argv)
+{
+	return handle_command(kvm_commands, argc, (const char **) &argv[0]);
+}
+
+int main(int argc, char *argv[])
+{
+	kvm__set_dir("%s/%s", HOME_DIR, KVM_PID_FILE_PATH);
+
+	return handle_kvm_command(argc - 1, &argv[1]);
+}
diff --git a/tools/kvm/mmio.c b/tools/kvm/mmio.c
new file mode 100644
index 0000000..6e8d1bb
--- /dev/null
+++ b/tools/kvm/mmio.c
@@ -0,0 +1,135 @@
+#include "kvm/kvm.h"
+#include "kvm/rbtree-interval.h"
+#include "kvm/brlock.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+#include <linux/kvm.h>
+#include <linux/types.h>
+#include <linux/rbtree.h>
+
+#define mmio_node(n) rb_entry(n, struct mmio_mapping, node)
+
+struct mmio_mapping {
+	struct rb_int_node	node;
+	void			(*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr);
+	void			*ptr;
+};
+
+static struct rb_root mmio_tree = RB_ROOT;
+
+static struct mmio_mapping *mmio_search(struct rb_root *root, u64 addr, u64 len)
+{
+	struct rb_int_node *node;
+
+	node = rb_int_search_range(root, addr, addr + len);
+	if (node == NULL)
+		return NULL;
+
+	return mmio_node(node);
+}
+
+/* Find lowest match, Check for overlap */
+static struct mmio_mapping *mmio_search_single(struct rb_root *root, u64 addr)
+{
+	struct rb_int_node *node;
+
+	node = rb_int_search_single(root, addr);
+	if (node == NULL)
+		return NULL;
+
+	return mmio_node(node);
+}
+
+static int mmio_insert(struct rb_root *root, struct mmio_mapping *data)
+{
+	return rb_int_insert(root, &data->node);
+}
+
+static const char *to_direction(u8 is_write)
+{
+	if (is_write)
+		return "write";
+
+	return "read";
+}
+
+bool kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 phys_addr_len, bool coalesce,
+			void (*mmio_fn)(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr),
+			void *ptr)
+{
+	struct mmio_mapping *mmio;
+	struct kvm_coalesced_mmio_zone zone;
+	int ret;
+
+	mmio = malloc(sizeof(*mmio));
+	if (mmio == NULL)
+		return false;
+
+	*mmio = (struct mmio_mapping) {
+		.node = RB_INT_INIT(phys_addr, phys_addr + phys_addr_len),
+		.mmio_fn = mmio_fn,
+		.ptr	= ptr,
+	};
+
+	if (coalesce) {
+		zone = (struct kvm_coalesced_mmio_zone) {
+			.addr	= phys_addr,
+			.size	= phys_addr_len,
+		};
+		ret = ioctl(kvm->vm_fd, KVM_REGISTER_COALESCED_MMIO, &zone);
+		if (ret < 0) {
+			free(mmio);
+			return false;
+		}
+	}
+	br_write_lock();
+	ret = mmio_insert(&mmio_tree, mmio);
+	br_write_unlock();
+
+	return ret;
+}
+
+bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+	struct mmio_mapping *mmio;
+	struct kvm_coalesced_mmio_zone zone;
+
+	br_write_lock();
+	mmio = mmio_search_single(&mmio_tree, phys_addr);
+	if (mmio == NULL) {
+		br_write_unlock();
+		return false;
+	}
+
+	zone = (struct kvm_coalesced_mmio_zone) {
+		.addr	= phys_addr,
+		.size	= 1,
+	};
+	ioctl(kvm->vm_fd, KVM_UNREGISTER_COALESCED_MMIO, &zone);
+
+	rb_int_erase(&mmio_tree, &mmio->node);
+	br_write_unlock();
+
+	free(mmio);
+	return true;
+}
+
+bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+	struct mmio_mapping *mmio;
+
+	br_read_lock();
+	mmio = mmio_search(&mmio_tree, phys_addr, len);
+
+	if (mmio)
+		mmio->mmio_fn(phys_addr, data, len, is_write, mmio->ptr);
+	else
+		fprintf(stderr, "Warning: Ignoring MMIO %s at %016llx (length %u)\n",
+			to_direction(is_write), phys_addr, len);
+	br_read_unlock();
+
+	return true;
+}
diff --git a/tools/kvm/net/uip/arp.c b/tools/kvm/net/uip/arp.c
new file mode 100644
index 0000000..98423da
--- /dev/null
+++ b/tools/kvm/net/uip/arp.c
@@ -0,0 +1,30 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_arp(struct uip_tx_arg *arg)
+{
+	struct uip_arp *arp, *arp2;
+	struct uip_info *info;
+	struct uip_buf *buf;
+
+	info = arg->info;
+	buf = uip_buf_clone(arg);
+
+	arp	 = (struct uip_arp *)(arg->eth);
+	arp2	 = (struct uip_arp *)(buf->eth);
+
+	/*
+	 * ARP replay code: 2
+	 */
+	arp2->op   = htons(0x2);
+	arp2->dmac = arp->smac;
+	arp2->dip  = arp->sip;
+
+	if (arp->dip == htonl(info->host_ip)) {
+		arp2->smac = info->host_mac;
+		arp2->sip = htonl(info->host_ip);
+
+		uip_buf_set_used(info, buf);
+	}
+
+	return 0;
+}
diff --git a/tools/kvm/net/uip/buf.c b/tools/kvm/net/uip/buf.c
new file mode 100644
index 0000000..5e564a9
--- /dev/null
+++ b/tools/kvm/net/uip/buf.c
@@ -0,0 +1,114 @@
+#include "kvm/uip.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+struct uip_buf *uip_buf_get_used(struct uip_info *info)
+{
+	struct uip_buf *buf;
+	bool found = false;
+
+	mutex_lock(&info->buf_lock);
+
+	while (!(info->buf_used_nr > 0))
+		pthread_cond_wait(&info->buf_used_cond, &info->buf_lock);
+
+	list_for_each_entry(buf, &info->buf_head, list) {
+		if (buf->status == UIP_BUF_STATUS_USED) {
+			/*
+			 * Set status to INUSE immediately to prevent
+			 * someone from using this buf until we free it
+			 */
+			buf->status = UIP_BUF_STATUS_INUSE;
+			info->buf_used_nr--;
+			found = true;
+			break;
+		}
+	}
+
+	mutex_unlock(&info->buf_lock);
+
+	return found ? buf : NULL;
+}
+
+struct uip_buf *uip_buf_get_free(struct uip_info *info)
+{
+	struct uip_buf *buf;
+	bool found = false;
+
+	mutex_lock(&info->buf_lock);
+
+	while (!(info->buf_free_nr > 0))
+		pthread_cond_wait(&info->buf_free_cond, &info->buf_lock);
+
+	list_for_each_entry(buf, &info->buf_head, list) {
+		if (buf->status == UIP_BUF_STATUS_FREE) {
+			/*
+			 * Set status to INUSE immediately to prevent
+			 * someone from using this buf until we free it
+			 */
+			buf->status = UIP_BUF_STATUS_INUSE;
+			info->buf_free_nr--;
+			found = true;
+			break;
+		}
+	}
+
+	mutex_unlock(&info->buf_lock);
+
+	return found ? buf : NULL;
+}
+
+struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf)
+{
+	mutex_lock(&info->buf_lock);
+
+	buf->status = UIP_BUF_STATUS_USED;
+	info->buf_used_nr++;
+	pthread_cond_signal(&info->buf_used_cond);
+
+	mutex_unlock(&info->buf_lock);
+
+	return buf;
+}
+
+struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf)
+{
+	mutex_lock(&info->buf_lock);
+
+	buf->status = UIP_BUF_STATUS_FREE;
+	info->buf_free_nr++;
+	pthread_cond_signal(&info->buf_free_cond);
+
+	mutex_unlock(&info->buf_lock);
+
+	return buf;
+}
+
+struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg)
+{
+	struct uip_buf *buf;
+	struct uip_eth *eth2;
+	struct uip_info *info;
+
+	info = arg->info;
+
+	/*
+	 * Get buffer from device to guest
+	 */
+	buf = uip_buf_get_free(info);
+
+	/*
+	 * Clone buffer
+	 */
+	memcpy(buf->vnet, arg->vnet, arg->vnet_len);
+	memcpy(buf->eth, arg->eth, arg->eth_len);
+	buf->vnet_len	= arg->vnet_len;
+	buf->eth_len	= arg->eth_len;
+
+	eth2		= (struct uip_eth *)buf->eth;
+	eth2->src	= info->host_mac;
+	eth2->dst	= arg->eth->src;
+
+	return buf;
+}
diff --git a/tools/kvm/net/uip/core.c b/tools/kvm/net/uip/core.c
new file mode 100644
index 0000000..2e7603c
--- /dev/null
+++ b/tools/kvm/net/uip/core.c
@@ -0,0 +1,190 @@
+#include "kvm/mutex.h"
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+int uip_tx(struct iovec *iov, u16 out, struct uip_info *info)
+{
+	struct virtio_net_hdr *vnet;
+	struct uip_tx_arg arg;
+	int eth_len, vnet_len;
+	struct uip_eth *eth;
+	u8 *buf = NULL;
+	u16 proto;
+	int i;
+
+	/*
+	 * Buffer from guest to device
+	 */
+	vnet_len = iov[0].iov_len;
+	vnet	 = iov[0].iov_base;
+
+	eth_len	 = iov[1].iov_len;
+	eth	 = iov[1].iov_base;
+
+	/*
+	 * In case, ethernet frame is in more than one iov entry.
+	 * Copy iov buffer into one linear buffer.
+	 */
+	if (out > 2) {
+		eth_len = 0;
+		for (i = 1; i < out; i++)
+			eth_len += iov[i].iov_len;
+
+		buf = malloc(eth_len);
+		if (!buf)
+			return -1;
+
+		eth = (struct uip_eth *)buf;
+		for (i = 1; i < out; i++) {
+			memcpy(buf, iov[i].iov_base, iov[i].iov_len);
+			buf += iov[i].iov_len;
+		}
+	}
+
+	memset(&arg, 0, sizeof(arg));
+
+	arg.vnet_len = vnet_len;
+	arg.eth_len = eth_len;
+	arg.info = info;
+	arg.vnet = vnet;
+	arg.eth = eth;
+
+	/*
+	 * Check package type
+	 */
+	proto = ntohs(eth->type);
+
+	switch (proto) {
+	case UIP_ETH_P_ARP:
+		uip_tx_do_arp(&arg);
+		break;
+	case UIP_ETH_P_IP:
+		uip_tx_do_ipv4(&arg);
+		break;
+	default:
+		break;
+	}
+
+	if (out > 2 && buf)
+		free(eth);
+
+	return vnet_len + eth_len;
+}
+
+int uip_rx(struct iovec *iov, u16 in, struct uip_info *info)
+{
+	struct virtio_net_hdr *vnet;
+	struct uip_eth *eth;
+	struct uip_buf *buf;
+	int vnet_len;
+	int eth_len;
+	char *p;
+	int len;
+	int cnt;
+	int i;
+
+	/*
+	 * Sleep until there is a buffer for guest
+	 */
+	buf = uip_buf_get_used(info);
+
+	/*
+	 * Fill device to guest buffer, vnet hdr fisrt
+	 */
+	vnet_len = iov[0].iov_len;
+	vnet = iov[0].iov_base;
+	if (buf->vnet_len > vnet_len) {
+		len = -1;
+		goto out;
+	}
+	memcpy(vnet, buf->vnet, buf->vnet_len);
+
+	/*
+	 * Then, the real eth data
+	 * Note: Be sure buf->eth_len is not bigger than the buffer len that guest provides
+	 */
+	cnt = buf->eth_len;
+	p = buf->eth;
+	for (i = 1; i < in; i++) {
+		eth_len = iov[i].iov_len;
+		eth = iov[i].iov_base;
+		if (cnt > eth_len) {
+			memcpy(eth, p, eth_len);
+			cnt -= eth_len;
+			p += eth_len;
+		} else {
+			memcpy(eth, p, cnt);
+			cnt -= cnt;
+			break;
+		}
+	}
+
+	if (cnt) {
+		pr_warning("uip_rx error");
+		len = -1;
+		goto out;
+	}
+
+	len = buf->vnet_len + buf->eth_len;
+
+out:
+	uip_buf_set_free(info, buf);
+	return len;
+}
+
+int uip_init(struct uip_info *info)
+{
+	struct list_head *udp_socket_head;
+	struct list_head *tcp_socket_head;
+	struct list_head *buf_head;
+	struct uip_buf *buf;
+	int buf_nr;
+	int i;
+
+	udp_socket_head	= &info->udp_socket_head;
+	tcp_socket_head	= &info->tcp_socket_head;
+	buf_head	= &info->buf_head;
+	buf_nr		= info->buf_nr;
+
+	INIT_LIST_HEAD(udp_socket_head);
+	INIT_LIST_HEAD(tcp_socket_head);
+	INIT_LIST_HEAD(buf_head);
+
+	pthread_mutex_init(&info->udp_socket_lock, NULL);
+	pthread_mutex_init(&info->tcp_socket_lock, NULL);
+	pthread_mutex_init(&info->buf_lock, NULL);
+
+	pthread_cond_init(&info->buf_used_cond, NULL);
+	pthread_cond_init(&info->buf_free_cond, NULL);
+
+
+	for (i = 0; i < buf_nr; i++) {
+		buf = malloc(sizeof(*buf));
+		memset(buf, 0, sizeof(*buf));
+
+		buf->status	= UIP_BUF_STATUS_FREE;
+		buf->info	= info;
+		buf->id		= i;
+		list_add_tail(&buf->list, buf_head);
+	}
+
+	list_for_each_entry(buf, buf_head, list) {
+		buf->vnet	= malloc(sizeof(struct virtio_net_hdr));
+		buf->vnet_len	= sizeof(struct virtio_net_hdr);
+		buf->eth	= malloc(1024*64 + sizeof(struct uip_pseudo_hdr));
+		buf->eth_len	= 1024*64 + sizeof(struct uip_pseudo_hdr);
+
+		memset(buf->vnet, 0, buf->vnet_len);
+		memset(buf->eth, 0, buf->eth_len);
+	}
+
+	info->buf_free_nr = buf_nr;
+	info->buf_used_nr = 0;
+
+	uip_dhcp_get_dns(info);
+
+	return 0;
+}
diff --git a/tools/kvm/net/uip/csum.c b/tools/kvm/net/uip/csum.c
new file mode 100644
index 0000000..7ca8bad
--- /dev/null
+++ b/tools/kvm/net/uip/csum.c
@@ -0,0 +1,92 @@
+#include "kvm/uip.h"
+
+static u16 uip_csum(u16 csum, u8 *addr, u16 count)
+{
+	long sum = csum;
+
+	while (count > 1) {
+		sum	+= *(u16 *)addr;
+		addr	+= 2;
+		count	-= 2;
+	}
+
+	if (count > 0)
+		sum += *(unsigned char *)addr;
+
+	while (sum>>16)
+		sum = (sum & 0xffff) + (sum >> 16);
+
+	return ~sum;
+}
+
+u16 uip_csum_ip(struct uip_ip *ip)
+{
+	return uip_csum(0, &ip->vhl, uip_ip_hdrlen(ip));
+}
+
+u16 uip_csum_icmp(struct uip_icmp *icmp)
+{
+	struct uip_ip *ip;
+
+	ip = &icmp->ip;
+	return icmp->csum = uip_csum(0, &icmp->type, htons(ip->len) - uip_ip_hdrlen(ip) - 8); /* icmp header len = 8 */
+}
+
+u16 uip_csum_udp(struct uip_udp *udp)
+{
+	struct uip_pseudo_hdr hdr;
+	struct uip_ip *ip;
+	int udp_len;
+	u8 *pad;
+
+	ip	  = &udp->ip;
+
+	hdr.sip   = ip->sip;
+	hdr.dip	  = ip->dip;
+	hdr.zero  = 0;
+	hdr.proto = ip->proto;
+	hdr.len   = udp->len;
+
+	udp_len	  = uip_udp_len(udp);
+
+	if (udp_len % 2) {
+		pad = (u8 *)&udp->sport + udp_len;
+		*pad = 0;
+		memcpy((u8 *)&udp->sport + udp_len + 1, &hdr, sizeof(hdr));
+		return uip_csum(0, (u8 *)&udp->sport, udp_len + 1 + sizeof(hdr));
+	} else {
+		memcpy((u8 *)&udp->sport + udp_len, &hdr, sizeof(hdr));
+		return uip_csum(0, (u8 *)&udp->sport, udp_len + sizeof(hdr));
+	}
+
+}
+
+u16 uip_csum_tcp(struct uip_tcp *tcp)
+{
+	struct uip_pseudo_hdr hdr;
+	struct uip_ip *ip;
+	u16 tcp_len;
+	u8 *pad;
+
+	ip	  = &tcp->ip;
+	tcp_len   = ntohs(ip->len) - uip_ip_hdrlen(ip);
+
+	hdr.sip   = ip->sip;
+	hdr.dip	  = ip->dip;
+	hdr.zero  = 0;
+	hdr.proto = ip->proto;
+	hdr.len   = htons(tcp_len);
+
+	if (tcp_len > UIP_MAX_TCP_PAYLOAD + 20)
+		pr_warning("tcp_len(%d) is too large", tcp_len);
+
+	if (tcp_len % 2) {
+		pad = (u8 *)&tcp->sport + tcp_len;
+		*pad = 0;
+		memcpy((u8 *)&tcp->sport + tcp_len + 1, &hdr, sizeof(hdr));
+		return uip_csum(0, (u8 *)&tcp->sport, tcp_len + 1 + sizeof(hdr));
+	} else {
+		memcpy((u8 *)&tcp->sport + tcp_len, &hdr, sizeof(hdr));
+		return uip_csum(0, (u8 *)&tcp->sport, tcp_len + sizeof(hdr));
+	}
+}
diff --git a/tools/kvm/net/uip/dhcp.c b/tools/kvm/net/uip/dhcp.c
new file mode 100644
index 0000000..e91a7c7
--- /dev/null
+++ b/tools/kvm/net/uip/dhcp.c
@@ -0,0 +1,203 @@
+#include "kvm/uip.h"
+
+#include <arpa/inet.h>
+
+#define EMPTY_ADDR "0.0.0.0"
+
+static inline bool uip_dhcp_is_discovery(struct uip_dhcp *dhcp)
+{
+	return (dhcp->option[2] == UIP_DHCP_DISCOVER &&
+		dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
+		dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
+}
+
+static inline bool uip_dhcp_is_request(struct uip_dhcp *dhcp)
+{
+	return (dhcp->option[2] == UIP_DHCP_REQUEST &&
+		dhcp->option[1] == UIP_DHCP_TAG_MSG_TYPE_LEN &&
+		dhcp->option[0] == UIP_DHCP_TAG_MSG_TYPE);
+}
+
+bool uip_udp_is_dhcp(struct uip_udp *udp)
+{
+	struct uip_dhcp *dhcp;
+
+	if (ntohs(udp->sport) != UIP_DHCP_PORT_CLIENT ||
+	    ntohs(udp->dport) != UIP_DHCP_PORT_SERVER)
+		return false;
+
+	dhcp = (struct uip_dhcp *)udp;
+
+	if (ntohl(dhcp->magic_cookie) != UIP_DHCP_MAGIC_COOKIE)
+		return false;
+
+	return true;
+}
+
+int uip_dhcp_get_dns(struct uip_info *info)
+{
+	char key[256], val[256];
+	struct in_addr addr;
+	int ret = -1;
+	int n = 0;
+	FILE *fp;
+	u32 ip;
+
+	fp = fopen("/etc/resolv.conf", "r");
+	if (!fp)
+		goto out;
+
+	while (!feof(fp)) {
+		if (fscanf(fp, "%s %s\n", key, val) != 2)
+			continue;
+		if (strncmp("domain", key, 6) == 0)
+			info->domain_name = strndup(val, UIP_DHCP_MAX_DOMAIN_NAME_LEN);
+		else if (strncmp("nameserver", key, 10) == 0) {
+			if (!inet_aton(val, &addr))
+				continue;
+			ip = ntohl(addr.s_addr);
+			if (n < UIP_DHCP_MAX_DNS_SERVER_NR)
+				info->dns_ip[n++] = ip;
+			ret = 0;
+		}
+	}
+
+out:
+	fclose(fp);
+	return ret;
+}
+
+static int uip_dhcp_fill_option_name_and_server(struct uip_info *info, u8 *opt, int i)
+{
+	u8 domain_name_len;
+	u32 *addr;
+	int n;
+
+	if (info->domain_name) {
+		domain_name_len	= strlen(info->domain_name);
+		opt[i++]	= UIP_DHCP_TAG_DOMAIN_NAME;
+		opt[i++]	= domain_name_len;
+		memcpy(&opt[i], info->domain_name, domain_name_len);
+		i		+= domain_name_len;
+	}
+
+	for (n = 0; n < UIP_DHCP_MAX_DNS_SERVER_NR; n++) {
+		if (info->dns_ip[n] == 0)
+			continue;
+		opt[i++]	= UIP_DHCP_TAG_DNS_SERVER;
+		opt[i++]	= UIP_DHCP_TAG_DNS_SERVER_LEN;
+		addr		= (u32 *)&opt[i];
+		*addr		= htonl(info->dns_ip[n]);
+		i		+= UIP_DHCP_TAG_DNS_SERVER_LEN;
+	}
+
+	return i;
+}
+static int uip_dhcp_fill_option(struct uip_info *info, struct uip_dhcp *dhcp, int reply_msg_type)
+{
+	int i = 0;
+	u32 *addr;
+	u8 *opt;
+
+	opt		= dhcp->option;
+
+	opt[i++]	= UIP_DHCP_TAG_MSG_TYPE;
+	opt[i++]	= UIP_DHCP_TAG_MSG_TYPE_LEN;
+	opt[i++]	= reply_msg_type;
+
+	opt[i++]	= UIP_DHCP_TAG_SERVER_ID;
+	opt[i++]	= UIP_DHCP_TAG_SERVER_ID_LEN;
+	addr		= (u32 *)&opt[i];
+	*addr		= htonl(info->host_ip);
+	i		+= UIP_DHCP_TAG_SERVER_ID_LEN;
+
+	opt[i++]	= UIP_DHCP_TAG_LEASE_TIME;
+	opt[i++]	= UIP_DHCP_TAG_LEASE_TIME_LEN;
+	addr		= (u32 *)&opt[i];
+	*addr		= htonl(UIP_DHCP_LEASE_TIME);
+	i		+= UIP_DHCP_TAG_LEASE_TIME_LEN;
+
+	opt[i++]	= UIP_DHCP_TAG_SUBMASK;
+	opt[i++]	= UIP_DHCP_TAG_SUBMASK_LEN;
+	addr		= (u32 *)&opt[i];
+	*addr		= htonl(info->guest_netmask);
+	i		+= UIP_DHCP_TAG_SUBMASK_LEN;
+
+	opt[i++]	= UIP_DHCP_TAG_ROUTER;
+	opt[i++]	= UIP_DHCP_TAG_ROUTER_LEN;
+	addr		= (u32 *)&opt[i];
+	*addr		= htonl(info->host_ip);
+	i		+= UIP_DHCP_TAG_ROUTER_LEN;
+
+	opt[i++]	= UIP_DHCP_TAG_ROOT;
+	opt[i++]	= strlen(EMPTY_ADDR);
+	addr		= (u32 *)&opt[i];
+	strncpy((void *) addr, EMPTY_ADDR, strlen(EMPTY_ADDR));
+	i		+= strlen(EMPTY_ADDR);
+
+	i 		= uip_dhcp_fill_option_name_and_server(info, opt, i);
+
+	opt[i++]	= UIP_DHCP_TAG_END;
+
+	return 0;
+}
+
+static int uip_dhcp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8 reply_msg_type)
+{
+	struct uip_dhcp *dhcp;
+
+	dhcp		= (struct uip_dhcp *)buf->eth;
+
+	dhcp->msg_type	= 2;
+	dhcp->client_ip	= 0;
+	dhcp->your_ip	= htonl(info->guest_ip);
+	dhcp->server_ip	= htonl(info->host_ip);
+	dhcp->agent_ip	= 0;
+
+	uip_dhcp_fill_option(info, dhcp, reply_msg_type);
+
+	sk->sip		= htonl(info->guest_ip);
+	sk->dip		= htonl(info->host_ip);
+	sk->sport	= htons(UIP_DHCP_PORT_CLIENT);
+	sk->dport	= htons(UIP_DHCP_PORT_SERVER);
+
+	return 0;
+}
+
+int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg)
+{
+	struct uip_udp_socket sk;
+	struct uip_dhcp *dhcp;
+	struct uip_info *info;
+	struct uip_buf *buf;
+	u8 reply_msg_type;
+
+	dhcp = (struct uip_dhcp *)arg->eth;
+
+	if (uip_dhcp_is_discovery(dhcp))
+		reply_msg_type = UIP_DHCP_OFFER;
+	else if (uip_dhcp_is_request(dhcp))
+		reply_msg_type = UIP_DHCP_ACK;
+	else
+		return -1;
+
+	buf = uip_buf_clone(arg);
+	info = arg->info;
+
+	/*
+	 * Cook DHCP pkg
+	 */
+	uip_dhcp_make_pkg(info, &sk, buf, reply_msg_type);
+
+	/*
+	 * Cook UDP pkg
+	 */
+	uip_udp_make_pkg(info, &sk, buf, NULL, UIP_DHCP_MAX_PAYLOAD_LEN);
+
+	/*
+	 * Send data received from socket to guest
+	 */
+	uip_buf_set_used(info, buf);
+
+	return 0;
+}
diff --git a/tools/kvm/net/uip/icmp.c b/tools/kvm/net/uip/icmp.c
new file mode 100644
index 0000000..233297c
--- /dev/null
+++ b/tools/kvm/net/uip/icmp.c
@@ -0,0 +1,29 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_ipv4_icmp(struct uip_tx_arg *arg)
+{
+	struct uip_ip *ip, *ip2;
+	struct uip_icmp *icmp2;
+	struct uip_buf *buf;
+
+	buf		= uip_buf_clone(arg);
+
+	icmp2		= (struct uip_icmp *)(buf->eth);
+	ip2		= (struct uip_ip *)(buf->eth);
+	ip		= (struct uip_ip *)(arg->eth);
+
+	ip2->sip	= ip->dip;
+	ip2->dip	= ip->sip;
+	ip2->csum	= 0;
+	/*
+	 * ICMP reply: 0
+	 */
+	icmp2->type	= 0;
+	icmp2->csum	= 0;
+	ip2->csum	= uip_csum_ip(ip2);
+	icmp2->csum	= uip_csum_icmp(icmp2);
+
+	uip_buf_set_used(arg->info, buf);
+
+	return 0;
+}
diff --git a/tools/kvm/net/uip/ipv4.c b/tools/kvm/net/uip/ipv4.c
new file mode 100644
index 0000000..58373fd
--- /dev/null
+++ b/tools/kvm/net/uip/ipv4.c
@@ -0,0 +1,29 @@
+#include "kvm/uip.h"
+
+int uip_tx_do_ipv4(struct uip_tx_arg *arg)
+{
+	struct uip_ip *ip;
+
+	ip = (struct uip_ip *)(arg->eth);
+
+	if (uip_ip_hdrlen(ip) != 20) {
+		pr_warning("IP header length is not 20 bytes");
+		return -1;
+	}
+
+	switch (ip->proto) {
+	case UIP_IP_P_ICMP:
+		uip_tx_do_ipv4_icmp(arg);
+		break;
+	case UIP_IP_P_TCP:
+		uip_tx_do_ipv4_tcp(arg);
+		break;
+	case UIP_IP_P_UDP:
+		uip_tx_do_ipv4_udp(arg);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
diff --git a/tools/kvm/net/uip/tcp.c b/tools/kvm/net/uip/tcp.c
new file mode 100644
index 0000000..586a45c
--- /dev/null
+++ b/tools/kvm/net/uip/tcp.c
@@ -0,0 +1,317 @@
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+static int uip_tcp_socket_close(struct uip_tcp_socket *sk, int how)
+{
+	shutdown(sk->fd, how);
+
+	if (sk->write_done && sk->read_done) {
+		shutdown(sk->fd, SHUT_RDWR);
+		close(sk->fd);
+
+		mutex_lock(sk->lock);
+		list_del(&sk->list);
+		mutex_unlock(sk->lock);
+
+		free(sk);
+	}
+
+	return 0;
+}
+
+static struct uip_tcp_socket *uip_tcp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+	struct list_head *sk_head;
+	pthread_mutex_t *sk_lock;
+	struct uip_tcp_socket *sk;
+
+	sk_head = &arg->info->tcp_socket_head;
+	sk_lock = &arg->info->tcp_socket_lock;
+
+	mutex_lock(sk_lock);
+	list_for_each_entry(sk, sk_head, list) {
+		if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) {
+			mutex_unlock(sk_lock);
+			return sk;
+		}
+	}
+	mutex_unlock(sk_lock);
+
+	return NULL;
+}
+
+static struct uip_tcp_socket *uip_tcp_socket_alloc(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+	struct list_head *sk_head;
+	struct uip_tcp_socket *sk;
+	pthread_mutex_t *sk_lock;
+	struct uip_tcp *tcp;
+	struct uip_ip *ip;
+	int ret;
+
+	tcp = (struct uip_tcp *)arg->eth;
+	ip = (struct uip_ip *)arg->eth;
+
+	sk_head = &arg->info->tcp_socket_head;
+	sk_lock = &arg->info->tcp_socket_lock;
+
+	sk = malloc(sizeof(*sk));
+	memset(sk, 0, sizeof(*sk));
+
+	sk->lock			= sk_lock;
+	sk->info			= arg->info;
+
+	sk->fd				= socket(AF_INET, SOCK_STREAM, 0);
+	sk->addr.sin_family		= AF_INET;
+	sk->addr.sin_addr.s_addr	= dip;
+	sk->addr.sin_port		= dport;
+
+	ret = connect(sk->fd, (struct sockaddr *)&sk->addr, sizeof(sk->addr));
+	if (ret) {
+		free(sk);
+		return NULL;
+	}
+
+	sk->sip		= ip->sip;
+	sk->dip		= ip->dip;
+	sk->sport	= tcp->sport;
+	sk->dport	= tcp->dport;
+
+	mutex_lock(sk_lock);
+	list_add_tail(&sk->list, sk_head);
+	mutex_unlock(sk_lock);
+
+	return sk;
+}
+
+static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len)
+{
+	struct uip_info *info;
+	struct uip_eth *eth2;
+	struct uip_tcp *tcp2;
+	struct uip_buf *buf;
+	struct uip_ip *ip2;
+
+	info		= sk->info;
+
+	/*
+	 * Get free buffer to send data to guest
+	 */
+	buf		= uip_buf_get_free(info);
+
+	/*
+	 * Cook a ethernet frame
+	 */
+	tcp2		= (struct uip_tcp *)buf->eth;
+	eth2		= (struct uip_eth *)buf->eth;
+	ip2		= (struct uip_ip *)buf->eth;
+
+	eth2->src	= info->host_mac;
+	eth2->dst	= info->guest_mac;
+	eth2->type	= htons(UIP_ETH_P_IP);
+
+	ip2->vhl	= UIP_IP_VER_4 | UIP_IP_HDR_LEN;
+	ip2->tos	= 0;
+	ip2->id		= 0;
+	ip2->flgfrag	= 0;
+	ip2->ttl	= UIP_IP_TTL;
+	ip2->proto	= UIP_IP_P_TCP;
+	ip2->csum	= 0;
+	ip2->sip	= sk->dip;
+	ip2->dip	= sk->sip;
+
+	tcp2->sport	= sk->dport;
+	tcp2->dport	= sk->sport;
+	tcp2->seq	= htonl(sk->seq_server);
+	tcp2->ack	= htonl(sk->ack_server);
+	/*
+	 * Diable TCP options, tcp hdr len equals 20 bytes
+	 */
+	tcp2->off	= UIP_TCP_HDR_LEN;
+	tcp2->flg	= flag;
+	tcp2->win	= htons(UIP_TCP_WIN_SIZE);
+	tcp2->csum	= 0;
+	tcp2->urgent	= 0;
+
+	if (payload_len > 0)
+		memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len);
+
+	ip2->len	= htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2));
+	ip2->csum	= uip_csum_ip(ip2);
+	tcp2->csum	= uip_csum_tcp(tcp2);
+
+	/*
+	 * virtio_net_hdr
+	 */
+	buf->vnet_len	= sizeof(struct virtio_net_hdr);
+	memset(buf->vnet, 0, buf->vnet_len);
+
+	buf->eth_len	= ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth);
+
+	/*
+	 * Increase server seq
+	 */
+	sk->seq_server  += payload_len;
+
+	/*
+	 * Send data received from socket to guest
+	 */
+	uip_buf_set_used(info, buf);
+
+	return 0;
+}
+
+static void *uip_tcp_socket_thread(void *p)
+{
+	struct uip_tcp_socket *sk;
+	u8 *payload;
+	int ret;
+
+	sk = p;
+
+	payload = malloc(UIP_MAX_TCP_PAYLOAD);
+	sk->payload = payload;
+	if (!sk->payload)
+		goto out;
+
+	while (1) {
+
+		ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD);
+
+		if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD)
+			goto out;
+
+		uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, ret);
+
+	}
+
+out:
+	/*
+	 * Close server to guest TCP connection
+	 */
+	uip_tcp_socket_close(sk, SHUT_RD);
+
+	uip_tcp_payload_send(sk, UIP_TCP_FLAG_FIN | UIP_TCP_FLAG_ACK, 0);
+	sk->seq_server += 1;
+
+	sk->read_done = 1;
+
+	free(sk->payload);
+	pthread_exit(NULL);
+
+	return NULL;
+}
+
+static int uip_tcp_socket_receive(struct uip_tcp_socket *sk)
+{
+	if (sk->thread == 0)
+		return pthread_create(&sk->thread, NULL, uip_tcp_socket_thread, (void *)sk);
+
+	return 0;
+}
+
+static int uip_tcp_socket_send(struct uip_tcp_socket *sk, struct uip_tcp *tcp)
+{
+	int len;
+	int ret;
+	u8 *payload;
+
+	if (sk->write_done)
+		return 0;
+
+	payload = uip_tcp_payload(tcp);
+	len = uip_tcp_payloadlen(tcp);
+
+	ret = write(sk->fd, payload, len);
+	if (ret != len)
+		pr_warning("tcp send error");
+
+	return ret;
+}
+
+int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg)
+{
+	struct uip_tcp_socket *sk;
+	struct uip_tcp *tcp;
+	struct uip_ip *ip;
+	int ret;
+
+	tcp = (struct uip_tcp *)arg->eth;
+	ip = (struct uip_ip *)arg->eth;
+
+	/*
+	 * Guest is trying to start a TCP session, let's fake SYN-ACK to guest
+	 */
+	if (uip_tcp_is_syn(tcp)) {
+		sk = uip_tcp_socket_alloc(arg, ip->sip, ip->dip, tcp->sport, tcp->dport);
+		if (!sk)
+			return -1;
+
+		/*
+		 * Setup ISN number
+		 */
+		sk->isn_guest  = uip_tcp_isn(tcp);
+		sk->isn_server = uip_tcp_isn_alloc();
+
+		sk->seq_server = sk->isn_server;
+		sk->ack_server = sk->isn_guest + 1;
+		uip_tcp_payload_send(sk, UIP_TCP_FLAG_SYN | UIP_TCP_FLAG_ACK, 0);
+		sk->seq_server += 1;
+
+		/*
+		 * Start receive thread for data from remote to guest
+		 */
+		uip_tcp_socket_receive(sk);
+
+		goto out;
+	}
+
+	/*
+	 * Find socket we have allocated
+	 */
+	sk = uip_tcp_socket_find(arg, ip->sip, ip->dip, tcp->sport, tcp->dport);
+	if (!sk)
+		return -1;
+
+	sk->guest_acked = ntohl(tcp->ack);
+
+	if (uip_tcp_is_fin(tcp)) {
+		if (sk->write_done)
+			goto out;
+
+		sk->write_done = 1;
+		sk->ack_server += 1;
+		uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0);
+
+		/*
+		 * Close guest to server TCP connection
+		 */
+		uip_tcp_socket_close(sk, SHUT_WR);
+
+		goto out;
+	}
+
+	/*
+	 * Ignore guest to server frames with zero tcp payload
+	 */
+	if (uip_tcp_payloadlen(tcp) == 0)
+		goto out;
+
+	/*
+	 * Sent out TCP data to remote host
+	 */
+	ret = uip_tcp_socket_send(sk, tcp);
+	if (ret < 0)
+		return -1;
+	/*
+	 * Send ACK to guest imediately
+	 */
+	sk->ack_server += ret;
+	uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0);
+
+out:
+	return 0;
+}
diff --git a/tools/kvm/net/uip/udp.c b/tools/kvm/net/uip/udp.c
new file mode 100644
index 0000000..d4518b2
--- /dev/null
+++ b/tools/kvm/net/uip/udp.c
@@ -0,0 +1,236 @@
+#include "kvm/uip.h"
+
+#include <linux/virtio_net.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <fcntl.h>
+
+#define UIP_UDP_MAX_EVENTS 1000
+
+static struct uip_udp_socket *uip_udp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport)
+{
+	struct list_head *sk_head;
+	struct uip_udp_socket *sk;
+	pthread_mutex_t *sk_lock;
+	struct epoll_event ev;
+	int flags;
+	int ret;
+
+	sk_head = &arg->info->udp_socket_head;
+	sk_lock = &arg->info->udp_socket_lock;
+
+	/*
+	 * Find existing sk
+	 */
+	mutex_lock(sk_lock);
+	list_for_each_entry(sk, sk_head, list) {
+		if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) {
+			mutex_unlock(sk_lock);
+			return sk;
+		}
+	}
+	mutex_unlock(sk_lock);
+
+	/*
+	 * Allocate new one
+	 */
+	sk = malloc(sizeof(*sk));
+	memset(sk, 0, sizeof(*sk));
+
+	sk->lock = sk_lock;
+
+	sk->fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sk->fd < 0)
+		goto out;
+
+	/*
+	 * Set non-blocking
+	 */
+	flags = fcntl(sk->fd, F_GETFL, 0);
+	flags |= O_NONBLOCK;
+	fcntl(sk->fd, F_SETFL, flags);
+
+	/*
+	 * Add sk->fd to epoll_wait
+	 */
+	ev.events	= EPOLLIN;
+	ev.data.fd	= sk->fd;
+	ev.data.ptr	= sk;
+	if (arg->info->udp_epollfd <= 0)
+		arg->info->udp_epollfd = epoll_create(UIP_UDP_MAX_EVENTS);
+	ret = epoll_ctl(arg->info->udp_epollfd, EPOLL_CTL_ADD, sk->fd, &ev);
+	if (ret == -1)
+		pr_warning("epoll_ctl error");
+
+	sk->addr.sin_family	 = AF_INET;
+	sk->addr.sin_addr.s_addr = dip;
+	sk->addr.sin_port	 = dport;
+
+	sk->sip			 = sip;
+	sk->dip			 = dip;
+	sk->sport		 = sport;
+	sk->dport		 = dport;
+
+	mutex_lock(sk_lock);
+	list_add_tail(&sk->list, sk_head);
+	mutex_unlock(sk_lock);
+
+	return sk;
+
+out:
+	free(sk);
+	return NULL;
+}
+
+static int uip_udp_socket_send(struct uip_udp_socket *sk, struct uip_udp *udp)
+{
+	int len;
+	int ret;
+
+	len = ntohs(udp->len) - uip_udp_hdrlen(udp);
+
+	ret = sendto(sk->fd, udp->payload, len, 0, (struct sockaddr *)&sk->addr, sizeof(sk->addr));
+	if (ret != len)
+		return -1;
+
+	return 0;
+}
+
+int uip_udp_make_pkg(struct uip_info *info, struct uip_udp_socket *sk, struct uip_buf *buf, u8* payload, int payload_len)
+{
+	struct uip_eth *eth2;
+	struct uip_udp *udp2;
+	struct uip_ip *ip2;
+
+	/*
+	 * Cook a ethernet frame
+	 */
+	udp2		= (struct uip_udp *)(buf->eth);
+	eth2		= (struct uip_eth *)buf->eth;
+	ip2		= (struct uip_ip *)(buf->eth);
+
+	eth2->src	= info->host_mac;
+	eth2->dst	= info->guest_mac;
+	eth2->type	= htons(UIP_ETH_P_IP);
+
+	ip2->vhl	= UIP_IP_VER_4 | UIP_IP_HDR_LEN;
+	ip2->tos	= 0;
+	ip2->id		= 0;
+	ip2->flgfrag	= 0;
+	ip2->ttl	= UIP_IP_TTL;
+	ip2->proto	= UIP_IP_P_UDP;
+	ip2->csum	= 0;
+
+	ip2->sip	= sk->dip;
+	ip2->dip	= sk->sip;
+	udp2->sport	= sk->dport;
+	udp2->dport	= sk->sport;
+
+	udp2->len	= htons(payload_len + uip_udp_hdrlen(udp2));
+	udp2->csum	= 0;
+
+	if (payload)
+		memcpy(udp2->payload, payload, payload_len);
+
+	ip2->len	= udp2->len + htons(uip_ip_hdrlen(ip2));
+	ip2->csum	= uip_csum_ip(ip2);
+	udp2->csum	= uip_csum_udp(udp2);
+
+	/*
+	 * virtio_net_hdr
+	 */
+	buf->vnet_len	= sizeof(struct virtio_net_hdr);
+	memset(buf->vnet, 0, buf->vnet_len);
+
+	buf->eth_len	= ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth);
+
+	return 0;
+}
+
+static void *uip_udp_socket_thread(void *p)
+{
+	struct epoll_event events[UIP_UDP_MAX_EVENTS];
+	struct uip_udp_socket *sk;
+	struct uip_info *info;
+	struct uip_buf *buf;
+	int payload_len;
+	u8 *payload;
+	int nfds;
+	int i;
+
+	info = p;
+
+	do {
+		payload = malloc(UIP_MAX_UDP_PAYLOAD);
+	} while (!payload);
+
+	while (1) {
+		nfds = epoll_wait(info->udp_epollfd, events, UIP_UDP_MAX_EVENTS, -1);
+
+		if (nfds == -1)
+			continue;
+
+		for (i = 0; i < nfds; i++) {
+
+			sk = events[i].data.ptr;
+			payload_len = recvfrom(sk->fd, payload, UIP_MAX_UDP_PAYLOAD, 0, NULL, NULL);
+			if (payload_len < 0)
+				continue;
+
+			/*
+			 * Get free buffer to send data to guest
+			 */
+			buf = uip_buf_get_free(info);
+
+			uip_udp_make_pkg(info, sk, buf, payload, payload_len);
+
+			/*
+			 * Send data received from socket to guest
+			 */
+			uip_buf_set_used(info, buf);
+		}
+	}
+
+	free(payload);
+	pthread_exit(NULL);
+	return NULL;
+}
+
+int uip_tx_do_ipv4_udp(struct uip_tx_arg *arg)
+{
+	struct uip_udp_socket *sk;
+	struct uip_info *info;
+	struct uip_udp *udp;
+	struct uip_ip *ip;
+	int ret;
+
+	udp	= (struct uip_udp *)(arg->eth);
+	ip	= (struct uip_ip *)(arg->eth);
+	info	= arg->info;
+
+	if (uip_udp_is_dhcp(udp)) {
+		uip_tx_do_ipv4_udp_dhcp(arg);
+		return 0;
+	}
+
+	/*
+	 * Find socket we have allocated before, otherwise allocate one
+	 */
+	sk = uip_udp_socket_find(arg, ip->sip, ip->dip, udp->sport, udp->dport);
+	if (!sk)
+		return -1;
+
+	/*
+	 * Send out UDP data to remote host
+	 */
+	ret = uip_udp_socket_send(sk, udp);
+	if (ret)
+		return -1;
+
+	if (!info->udp_thread)
+		pthread_create(&info->udp_thread, NULL, uip_udp_socket_thread, (void *)info);
+
+	return 0;
+}
diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c
new file mode 100644
index 0000000..41c4085
--- /dev/null
+++ b/tools/kvm/pci.c
@@ -0,0 +1,185 @@
+#include "kvm/pci.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#define PCI_BAR_OFFSET(b)		(offsetof(struct pci_device_header, bar[b]))
+
+static struct pci_device_header		*pci_devices[PCI_MAX_DEVICES];
+
+static union pci_config_address		pci_config_address;
+
+/* This is within our PCI gap - in an unused area.
+ * Note this is a PCI *bus address*, is used to assign BARs etc.!
+ * (That's why it can still 32bit even with 64bit guests-- 64bit
+ * PCI isn't currently supported.)
+ */
+static u32 io_space_blocks		= KVM_PCI_MMIO_AREA;
+
+u32 pci_get_io_space_block(u32 size)
+{
+	u32 block = io_space_blocks;
+	io_space_blocks += size;
+
+	return block;
+}
+
+static void *pci_config_address_ptr(u16 port)
+{
+	unsigned long offset;
+	void *base;
+
+	offset		= port - PCI_CONFIG_ADDRESS;
+	base		= &pci_config_address;
+
+	return base + offset;
+}
+
+static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	void *p = pci_config_address_ptr(port);
+
+	memcpy(p, data, size);
+
+	return true;
+}
+
+static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	void *p = pci_config_address_ptr(port);
+
+	memcpy(data, p, size);
+
+	return true;
+}
+
+static struct ioport_operations pci_config_address_ops = {
+	.io_in		= pci_config_address_in,
+	.io_out		= pci_config_address_out,
+};
+
+static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
+{
+	struct pci_device_header *dev;
+
+	if (pci_config_address.bus_number != bus_number)
+		return false;
+
+	if (pci_config_address.function_number != function_number)
+		return false;
+
+	if (device_number >= PCI_MAX_DEVICES)
+		return false;
+
+	dev		= pci_devices[device_number];
+
+	return dev != NULL;
+}
+
+static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	/*
+	 * If someone accesses PCI configuration space offsets that are not
+	 * aligned to 4 bytes, it uses ioports to signify that.
+	 */
+	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+
+	pci__config_wr(kvm, pci_config_address, data, size);
+
+	return true;
+}
+
+static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	/*
+	 * If someone accesses PCI configuration space offsets that are not
+	 * aligned to 4 bytes, it uses ioports to signify that.
+	 */
+	pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+
+	pci__config_rd(kvm, pci_config_address, data, size);
+
+	return true;
+}
+
+static struct ioport_operations pci_config_data_ops = {
+	.io_in		= pci_config_data_in,
+	.io_out		= pci_config_data_out,
+};
+
+void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data, int size)
+{
+	u8 dev_num;
+
+	dev_num		= addr.device_number;
+
+	if (pci_device_exists(0, dev_num, 0)) {
+		unsigned long offset;
+
+		offset = addr.w & 0xff;
+		if (offset < sizeof(struct pci_device_header)) {
+			void *p = pci_devices[dev_num];
+			u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32));
+			u32 sz = PCI_IO_SIZE;
+
+			if (bar < 6 && pci_devices[dev_num]->bar_size[bar])
+				sz = pci_devices[dev_num]->bar_size[bar];
+
+			/*
+			 * If the kernel masks the BAR it would expect to find the
+			 * size of the BAR there next time it reads from it.
+			 * When the kernel got the size it would write the address
+			 * back.
+			 */
+			if (*(u32 *)(p + offset)) {
+				/* See if kernel tries to mask one of the BARs */
+				if ((offset >= PCI_BAR_OFFSET(0)) &&
+				    (offset <= PCI_BAR_OFFSET(6)) &&
+				    (ioport__read32(data)  == 0xFFFFFFFF))
+					memcpy(p + offset, &sz, sizeof(sz));
+				    else
+					memcpy(p + offset, data, size);
+			}
+		}
+	}
+}
+
+void pci__config_rd(struct kvm *kvm, union pci_config_address addr, void *data, int size)
+{
+	u8 dev_num;
+
+	dev_num		= addr.device_number;
+
+	if (pci_device_exists(0, dev_num, 0)) {
+		unsigned long offset;
+
+		offset = addr.w & 0xff;
+		if (offset < sizeof(struct pci_device_header)) {
+			void *p = pci_devices[dev_num];
+
+			memcpy(data, p + offset, size);
+		} else {
+			memset(data, 0x00, size);
+		}
+	} else {
+		memset(data, 0xff, size);
+	}
+}
+
+void pci__register(struct pci_device_header *dev, u8 dev_num)
+{
+	BUG_ON(dev_num >= PCI_MAX_DEVICES);
+	pci_devices[dev_num]	= dev;
+}
+
+struct pci_device_header *pci__find_dev(u8 dev_num)
+{
+	BUG_ON(dev_num >= PCI_MAX_DEVICES);
+	return pci_devices[dev_num];
+}
+
+void pci__init(void)
+{
+	ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
+	ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
+}
diff --git a/tools/kvm/powerpc/include/kvm/barrier.h b/tools/kvm/powerpc/include/kvm/barrier.h
new file mode 100644
index 0000000..bc7d179
--- /dev/null
+++ b/tools/kvm/powerpc/include/kvm/barrier.h
@@ -0,0 +1,6 @@
+#ifndef _KVM_BARRIER_H_
+#define _KVM_BARRIER_H_
+
+#include <asm/system.h>
+
+#endif /* _KVM_BARRIER_H_ */
diff --git a/tools/kvm/powerpc/include/kvm/kvm-arch.h b/tools/kvm/powerpc/include/kvm/kvm-arch.h
new file mode 100644
index 0000000..c4b493c
--- /dev/null
+++ b/tools/kvm/powerpc/include/kvm/kvm-arch.h
@@ -0,0 +1,71 @@
+/*
+ * PPC64 architecture-specific definitions
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef KVM__KVM_ARCH_H
+#define KVM__KVM_ARCH_H
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+
+/*
+ * MMIO lives after RAM, but it'd be nice if it didn't constantly move.
+ * Choose a suitably high address, e.g. 63T...  This limits RAM size.
+ */
+#define PPC_MMIO_START			0x3F0000000000UL
+#define PPC_MMIO_SIZE			0x010000000000UL
+
+#define KERNEL_LOAD_ADDR        	0x0000000000000000
+#define KERNEL_START_ADDR       	0x0000000000000000
+#define KERNEL_SECONDARY_START_ADDR     0x0000000000000060
+#define INITRD_LOAD_ADDR        	0x0000000002800000
+
+#define FDT_MAX_SIZE            	0x10000
+#define RTAS_MAX_SIZE           	0x10000
+
+#define TIMEBASE_FREQ           	512000000ULL
+
+#define KVM_MMIO_START			PPC_MMIO_START
+
+/*
+ * This is the address that pci_get_io_space_block() starts allocating
+ * from.  Note that this is a PCI bus address.
+ */
+#define KVM_PCI_MMIO_AREA		0x1000000
+
+struct kvm {
+	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
+	int			vm_fd;		/* For VM ioctls() */
+	timer_t			timerid;	/* Posix timer for interrupts */
+
+	int			nrcpus;		/* Number of cpus to run */
+
+	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
+
+	u64			ram_size;
+	void			*ram_start;
+
+	bool			nmi_disabled;
+
+	bool			single_step;
+
+	const char		*vmlinux;
+	struct disk_image       **disks;
+	int                     nr_disks;
+	unsigned long		rtas_gra;
+	unsigned long		rtas_size;
+	unsigned long		fdt_gra;
+	unsigned long		initrd_gra;
+	unsigned long		initrd_size;
+	const char		*name;
+	int			vm_state;
+};
+
+#endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h b/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
new file mode 100644
index 0000000..64e4510
--- /dev/null
+++ b/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
@@ -0,0 +1,66 @@
+/*
+ * PPC64 cpu-specific definitions
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef KVM__KVM_CPU_ARCH_H
+#define KVM__KVM_CPU_ARCH_H
+
+/* Architecture-specific kvm_cpu definitions. */
+
+#include <linux/kvm.h>	/* for struct kvm_regs */
+
+#include <pthread.h>
+
+#define MSR_SF		(1UL<<63)
+#define MSR_HV		(1UL<<60)
+#define MSR_VEC		(1UL<<25)
+#define MSR_VSX		(1UL<<23)
+#define MSR_POW		(1UL<<18)
+#define MSR_EE		(1UL<<15)
+#define MSR_PR		(1UL<<14)
+#define MSR_FP		(1UL<<13)
+#define MSR_ME		(1UL<<12)
+#define MSR_FE0		(1UL<<11)
+#define MSR_SE		(1UL<<10)
+#define MSR_BE		(1UL<<9)
+#define MSR_FE1		(1UL<<8)
+#define MSR_IR		(1UL<<5)
+#define MSR_DR		(1UL<<4)
+#define MSR_PMM		(1UL<<2)
+#define MSR_RI		(1UL<<1)
+#define MSR_LE		(1UL<<0)
+
+struct kvm;
+
+struct kvm_cpu {
+	pthread_t		thread;		/* VCPU thread */
+
+	unsigned long		cpu_id;
+
+	struct kvm		*kvm;		/* parent KVM */
+	int			vcpu_fd;	/* For VCPU ioctls() */
+	struct kvm_run		*kvm_run;
+
+	struct kvm_regs		regs;
+	struct kvm_sregs	sregs;
+	struct kvm_fpu		fpu;
+
+	u8			is_running;
+	u8			paused;
+	u8			needs_nmi;
+	/*
+	 * Although PPC KVM doesn't yet support coalesced MMIO, generic code
+	 * needs this in our kvm_cpu:
+	 */
+	struct kvm_coalesced_mmio_ring  *ring;
+};
+
+void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level);
+
+#endif /* KVM__KVM_CPU_ARCH_H */
diff --git a/tools/kvm/powerpc/ioport.c b/tools/kvm/powerpc/ioport.c
new file mode 100644
index 0000000..a8e4dc3
--- /dev/null
+++ b/tools/kvm/powerpc/ioport.c
@@ -0,0 +1,18 @@
+/*
+ * PPC64 ioport platform setup.  There isn't any! :-)
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/ioport.h"
+
+#include <stdlib.h>
+
+void ioport__setup_arch(void)
+{
+	/* PPC has no legacy ioports to set up */
+}
diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
new file mode 100644
index 0000000..46aa64f
--- /dev/null
+++ b/tools/kvm/powerpc/irq.c
@@ -0,0 +1,40 @@
+/*
+ * PPC64 IRQ routines
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
+{
+	fprintf(stderr, "irq__register_device(%d, [%d], [%d], [%d]\n",
+		dev, *num, *pin, *line);
+	return 0;
+}
+
+void irq__init(struct kvm *kvm)
+{
+	fprintf(stderr, __func__);
+}
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+{
+	die(__FUNCTION__);
+	return 0;
+}
diff --git a/tools/kvm/powerpc/kvm-cpu.c b/tools/kvm/powerpc/kvm-cpu.c
new file mode 100644
index 0000000..ea99666
--- /dev/null
+++ b/tools/kvm/powerpc/kvm-cpu.c
@@ -0,0 +1,233 @@
+/*
+ * PPC64 processor support
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+static int debug_fd;
+
+void kvm_cpu__set_debug_fd(int fd)
+{
+	debug_fd = fd;
+}
+
+int kvm_cpu__get_debug_fd(void)
+{
+	return debug_fd;
+}
+
+static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
+{
+	struct kvm_cpu *vcpu;
+
+	vcpu		= calloc(1, sizeof *vcpu);
+	if (!vcpu)
+		return NULL;
+
+	vcpu->kvm	= kvm;
+
+	return vcpu;
+}
+
+void kvm_cpu__delete(struct kvm_cpu *vcpu)
+{
+	free(vcpu);
+}
+
+struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
+{
+	struct kvm_cpu *vcpu;
+	int mmap_size;
+	struct kvm_enable_cap papr_cap = { .cap = KVM_CAP_PPC_PAPR };
+
+	vcpu		= kvm_cpu__new(kvm);
+	if (!vcpu)
+		return NULL;
+
+	vcpu->cpu_id	= cpu_id;
+
+	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
+	if (vcpu->vcpu_fd < 0)
+		die_perror("KVM_CREATE_VCPU ioctl");
+
+	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
+	if (mmap_size < 0)
+		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
+
+	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
+	if (vcpu->kvm_run == MAP_FAILED)
+		die("unable to mmap vcpu fd");
+
+	ioctl(vcpu->vcpu_fd, KVM_ENABLE_CAP, &papr_cap);
+
+	/*
+	 * We start all CPUs, directing non-primary threads into the kernel's
+	 * secondary start point.  When we come to support SLOF, we will start
+	 * only one and SLOF will RTAS call us to ask for others to be
+	 * started.  (FIXME: make more generic & interface with whichever
+	 * firmware a platform may be using.)
+	 */
+	vcpu->is_running = true;
+
+	return vcpu;
+}
+
+static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
+{
+	/* Don't have to do anything, there's no expected FPU state. */
+}
+
+static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
+{
+	/*
+	 * FIXME: This assumes PPC64 and Linux guest.  It doesn't use the
+	 * OpenFirmware entry method, but instead the "embedded" entry which
+	 * passes the FDT address directly.
+	 */
+	struct kvm_regs *r = &vcpu->regs;
+
+	if (vcpu->cpu_id == 0) {
+		r->pc = KERNEL_START_ADDR;
+		r->gpr[3] = vcpu->kvm->fdt_gra;
+		r->gpr[5] = 0;
+	} else {
+		r->pc = KERNEL_SECONDARY_START_ADDR;
+		r->gpr[3] = vcpu->cpu_id;
+	}
+	r->msr = 0x8000000000001000UL; /* 64bit, non-HV, ME */
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
+		die_perror("KVM_SET_REGS failed");
+}
+
+static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
+{
+	/*
+	 * No sregs setup is required on PPC64/SPAPR (but there may be setup
+	 * required for non-paravirtualised platforms, e.g. TLB/SLB setup).
+	 */
+}
+
+/**
+ * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
+ */
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
+{
+	kvm_cpu__setup_regs(vcpu);
+	kvm_cpu__setup_sregs(vcpu);
+	kvm_cpu__setup_fpu(vcpu);
+}
+
+/* kvm_cpu__irq - set KVM's IRQ flag on this vcpu */
+void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level)
+{
+}
+
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
+{
+}
+
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
+{
+	bool ret = true;
+	struct kvm_run *run = vcpu->kvm_run;
+	switch(run->exit_reason) {
+	default:
+		ret = false;
+	}
+	return ret;
+}
+
+#define CONDSTR_BIT(m, b) (((m) & MSR_##b) ? #b" " : "")
+
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
+{
+	struct kvm_regs regs;
+	struct kvm_sregs sregs;
+	int r;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
+		die("KVM_GET_REGS failed");
+        if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+		die("KVM_GET_SREGS failed");
+
+	dprintf(debug_fd, "\n Registers:\n");
+	dprintf(debug_fd, " NIP:   %016llx  MSR:   %016llx "
+		"( %s%s%s%s%s%s%s%s%s%s%s%s)\n",
+		regs.pc, regs.msr,
+		CONDSTR_BIT(regs.msr, SF),
+		CONDSTR_BIT(regs.msr, HV), /* ! */
+		CONDSTR_BIT(regs.msr, VEC),
+		CONDSTR_BIT(regs.msr, VSX),
+		CONDSTR_BIT(regs.msr, EE),
+		CONDSTR_BIT(regs.msr, PR),
+		CONDSTR_BIT(regs.msr, FP),
+		CONDSTR_BIT(regs.msr, ME),
+		CONDSTR_BIT(regs.msr, IR),
+		CONDSTR_BIT(regs.msr, DR),
+		CONDSTR_BIT(regs.msr, RI),
+		CONDSTR_BIT(regs.msr, LE));
+	dprintf(debug_fd, " CTR:   %016llx  LR:    %016llx  CR:   %08llx\n",
+		regs.ctr, regs.lr, regs.cr);
+	dprintf(debug_fd, " SRR0:  %016llx  SRR1:  %016llx  XER:  %016llx\n",
+		regs.srr0, regs.srr1, regs.xer);
+	dprintf(debug_fd, " SPRG0: %016llx  SPRG1: %016llx\n",
+		regs.sprg0, regs.sprg1);
+	dprintf(debug_fd, " SPRG2: %016llx  SPRG3: %016llx\n",
+		regs.sprg2, regs.sprg3);
+	dprintf(debug_fd, " SPRG4: %016llx  SPRG5: %016llx\n",
+		regs.sprg4, regs.sprg5);
+	dprintf(debug_fd, " SPRG6: %016llx  SPRG7: %016llx\n",
+		regs.sprg6, regs.sprg7);
+	dprintf(debug_fd, " GPRs:\n ");
+	for (r = 0; r < 32; r++) {
+		dprintf(debug_fd, "%016llx  ", regs.gpr[r]);
+		if ((r & 3) == 3)
+			dprintf(debug_fd, "\n ");
+	}
+	dprintf(debug_fd, "\n");
+
+	/* FIXME: Assumes SLB-based (book3s) guest */
+	for (r = 0; r < 32; r++) {
+		dprintf(debug_fd, " SLB%02d  %016llx %016llx\n", r,
+			sregs.u.s.ppc64.slb[r].slbe,
+			sregs.u.s.ppc64.slb[r].slbv);
+	}
+	dprintf(debug_fd, "----------\n");
+}
+
+void kvm_cpu__show_code(struct kvm_cpu *vcpu)
+{
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
+		die("KVM_GET_REGS failed");
+
+	/* FIXME: Dump/disassemble some code...! */
+
+	dprintf(debug_fd, "\n Stack:\n");
+	dprintf(debug_fd,   " ------\n");
+	/* Only works in real mode: */
+	kvm__dump_mem(vcpu->kvm, vcpu->regs.gpr[1], 32);
+}
+
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
+{
+	/* Does nothing yet */
+}
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
new file mode 100644
index 0000000..627a66a
--- /dev/null
+++ b/tools/kvm/powerpc/kvm.c
@@ -0,0 +1,193 @@
+/*
+ * PPC64 (SPAPR) platform support
+ *
+ * Copyright 2011 Matt Evans <matt@ozlabs.org>, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <linux/kvm.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <asm/unistd.h>
+#include <errno.h>
+
+#include <linux/byteorder.h>
+#include <libfdt.h>
+
+#define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
+
+static char kern_cmdline[2048];
+
+struct kvm_ext kvm_req_ext[] = {
+	{ 0, 0 }
+};
+
+bool kvm__arch_cpu_supports_vm(void)
+{
+	return true;
+}
+
+void kvm__init_ram(struct kvm *kvm)
+{
+	u64	phys_start, phys_size;
+	void	*host_mem;
+
+	phys_start = 0;
+	phys_size  = kvm->ram_size;
+	host_mem   = kvm->ram_start;
+
+	/*
+	 * We put MMIO at PPC_MMIO_START, high up.  Make sure that this doesn't
+	 * crash into the end of RAM -- on PPC64 at least, this is so high
+	 * (63TB!) that this is unlikely.
+	 */
+	if (phys_size >= PPC_MMIO_START)
+		die("Too much memory (%lld, what a nice problem): "
+		    "overlaps MMIO!\n",
+		    phys_size);
+
+	kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+}
+
+void kvm__arch_set_cmdline(char *cmdline, bool video)
+{
+	/* We don't need anything unusual in here. */
+}
+
+/* Architecture-specific KVM init */
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
+{
+	int cap_ppc_rma;
+
+	kvm->ram_size		= ram_size;
+
+	/*
+	 * Currently, we must map from hugetlbfs; if --hugetlbfs not specified,
+	 * try a default path:
+	 */
+	if (!hugetlbfs_path) {
+		hugetlbfs_path = HUGETLBFS_PATH;
+		pr_info("Using default %s for memory", hugetlbfs_path);
+	}
+
+	kvm->ram_start = mmap_hugetlbfs(hugetlbfs_path, kvm->ram_size);
+	if (kvm->ram_start == MAP_FAILED)
+		die("Couldn't map %lld bytes for RAM (%d)\n",
+		    kvm->ram_size, errno);
+
+	/* FDT goes at top of memory, RTAS just below */
+	kvm->fdt_gra = kvm->ram_size - FDT_MAX_SIZE;
+	/* FIXME: Not all PPC systems have RTAS */
+	kvm->rtas_gra = kvm->fdt_gra - RTAS_MAX_SIZE;
+	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
+
+	/* FIXME: This is book3s-specific */
+	cap_ppc_rma = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_PPC_RMA);
+	if (cap_ppc_rma == 2)
+		die("Need contiguous RMA allocation on this hardware, "
+		    "which is not yet supported.");
+}
+
+void kvm__arch_delete_ram(struct kvm *kvm)
+{
+	munmap(kvm->ram_start, kvm->ram_size);
+}
+
+void kvm__irq_line(struct kvm *kvm, int irq, int level)
+{
+	fprintf(stderr, "irq_line(%d, %d)\n", irq, level);
+}
+
+void kvm__irq_trigger(struct kvm *kvm, int irq)
+{
+	kvm__irq_line(kvm, irq, 1);
+	kvm__irq_line(kvm, irq, 0);
+}
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
+{
+	void *p;
+	void *k_start;
+	void *i_start;
+	int nr;
+
+	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+		die_perror("lseek");
+
+	p = k_start = guest_flat_to_host(kvm, KERNEL_LOAD_ADDR);
+
+	while ((nr = read(fd_kernel, p, 65536)) > 0)
+		p += nr;
+
+	pr_info("Loaded kernel to 0x%x (%ld bytes)", KERNEL_LOAD_ADDR, p-k_start);
+
+	if (fd_initrd != -1) {
+		if (lseek(fd_initrd, 0, SEEK_SET) < 0)
+			die_perror("lseek");
+
+		if (p-k_start > INITRD_LOAD_ADDR)
+			die("Kernel overlaps initrd!");
+
+		/* Round up kernel size to 8byte alignment, and load initrd right after. */
+		i_start = p = guest_flat_to_host(kvm, INITRD_LOAD_ADDR);
+
+		while (((nr = read(fd_initrd, p, 65536)) > 0) &&
+		       p < (kvm->ram_start + kvm->ram_size))
+			p += nr;
+
+		if (p >= (kvm->ram_start + kvm->ram_size))
+			die("initrd too big to contain in guest RAM.\n");
+
+		pr_info("Loaded initrd to 0x%x (%ld bytes)",
+			INITRD_LOAD_ADDR, p-i_start);
+		kvm->initrd_gra = INITRD_LOAD_ADDR;
+		kvm->initrd_size = p-i_start;
+	} else {
+		kvm->initrd_size = 0;
+	}
+	strncpy(kern_cmdline, kernel_cmdline, 2048);
+	kern_cmdline[2047] = '\0';
+
+	return true;
+}
+
+bool load_bzimage(struct kvm *kvm, int fd_kernel,
+		  int fd_initrd, const char *kernel_cmdline, u16 vidmode)
+{
+	/* We don't support bzImages. */
+	return false;
+}
+
+static void setup_fdt(struct kvm *kvm)
+{
+
+}
+
+/**
+ * kvm__arch_setup_firmware
+ */
+int kvm__arch_setup_firmware(struct kvm *kvm)
+{
+	/* Load RTAS */
+
+	/* Load SLOF */
+
+	/* Init FDT */
+	setup_fdt(kvm);
+
+	return 0;
+}
diff --git a/tools/kvm/symbol.c b/tools/kvm/symbol.c
new file mode 100644
index 0000000..a2b1e67
--- /dev/null
+++ b/tools/kvm/symbol.c
@@ -0,0 +1,98 @@
+#include "kvm/symbol.h"
+
+#include "kvm/kvm.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <bfd.h>
+
+static bfd *abfd;
+
+void symbol__init(const char *vmlinux)
+{
+	if (!vmlinux)
+		return;
+
+	bfd_init();
+
+	abfd = bfd_openr(vmlinux, NULL);
+}
+
+static asymbol *lookup(asymbol **symbols, int nr_symbols, const char *symbol_name)
+{
+	int i;
+
+	for (i = 0; i < nr_symbols; i++) {
+		asymbol *symbol = symbols[i];
+
+		if (!strcmp(bfd_asymbol_name(symbol), symbol_name))
+			return symbol;
+	}
+
+	return NULL;
+}
+
+char *symbol__lookup(struct kvm *kvm, unsigned long addr, char *sym, size_t size)
+{
+	const char *filename;
+	bfd_vma sym_offset;
+	bfd_vma sym_start;
+	asection *section;
+	unsigned int line;
+	const char *func;
+	long symtab_size;
+	asymbol *symbol;
+	asymbol **syms;
+	int nr_syms;
+	char *s;
+
+	if (!abfd)
+		goto not_found;
+
+	if (!bfd_check_format(abfd, bfd_object))
+		goto not_found;
+
+	symtab_size = bfd_get_symtab_upper_bound(abfd);
+	if (!symtab_size)
+		goto not_found;
+
+	syms = malloc(symtab_size);
+	if (!syms)
+		goto not_found;
+
+	nr_syms = bfd_canonicalize_symtab(abfd, syms);
+
+	section = bfd_get_section_by_name(abfd, ".debug_aranges");
+	if (!section)
+		goto not_found;
+
+	if (!bfd_find_nearest_line(abfd, section, NULL, addr, &filename, &func, &line))
+		goto not_found;
+
+	if (!func)
+		goto not_found;
+
+	symbol = lookup(syms, nr_syms, func);
+	if (!symbol)
+		goto not_found;
+
+	sym_start = bfd_asymbol_value(symbol);
+
+	sym_offset = addr - sym_start;
+
+	snprintf(sym, size, "%s+%llx (%s:%i)", func, (long long) sym_offset, filename, line);
+
+	sym[size - 1] = '\0';
+
+	free(syms);
+
+	return sym;
+
+not_found:
+	s = strncpy(sym, "<unknown>", size);
+
+	sym[size - 1] = '\0';
+
+	return s;
+}
diff --git a/tools/kvm/term.c b/tools/kvm/term.c
new file mode 100644
index 0000000..cc0c5a5
--- /dev/null
+++ b/tools/kvm/term.c
@@ -0,0 +1,166 @@
+#include <poll.h>
+#include <stdbool.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include <signal.h>
+#include <pty.h>
+#include <utmp.h>
+
+#include "kvm/read-write.h"
+#include "kvm/term.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+
+#define TERM_FD_IN      0
+#define TERM_FD_OUT     1
+
+extern struct kvm *kvm;
+static struct termios	orig_term;
+
+int term_escape_char	= 0x01; /* ctrl-a is used for escape */
+bool term_got_escape	= false;
+
+int active_console;
+
+int term_fds[4][2];
+
+int term_getc(int who, int term)
+{
+	unsigned char c;
+
+	if (who != active_console)
+		return -1;
+	if (read_in_full(term_fds[term][TERM_FD_IN], &c, 1) < 0)
+		return -1;
+
+	if (term_got_escape) {
+		term_got_escape = false;
+		if (c == 'x')
+			kvm_cpu__reboot();
+		if (c == term_escape_char)
+			return c;
+	}
+
+	if (c == term_escape_char) {
+		term_got_escape = true;
+		return -1;
+	}
+
+	return c;
+}
+
+int term_putc(int who, char *addr, int cnt, int term)
+{
+	int ret;
+
+	if (who != active_console)
+		return -1;
+
+	while (cnt--) {
+		ret = write(term_fds[term][TERM_FD_OUT], addr++, 1);
+		if (ret < 0)
+			return 0;
+	}
+
+	return cnt;
+}
+
+int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term)
+{
+	int c;
+
+	if (who != active_console)
+		return 0;
+
+	c = term_getc(who, term);
+
+	if (c < 0)
+		return 0;
+
+	*((char *)iov[TERM_FD_IN].iov_base)	= (char)c;
+
+	return sizeof(char);
+}
+
+int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term)
+{
+	if (who != active_console)
+		return 0;
+
+	return writev(term_fds[term][TERM_FD_OUT], iov, iovcnt);
+}
+
+bool term_readable(int who, int term)
+{
+	struct pollfd pollfd = (struct pollfd) {
+		.fd	= term_fds[term][TERM_FD_IN],
+		.events	= POLLIN,
+		.revents = 0,
+	};
+
+	if (who != active_console)
+		return false;
+
+	return poll(&pollfd, 1, 0) > 0;
+}
+
+static void term_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < 4; i++)
+		tcsetattr(term_fds[i][TERM_FD_IN], TCSANOW, &orig_term);
+}
+
+static void term_sig_cleanup(int sig)
+{
+	term_cleanup();
+	signal(sig, SIG_DFL);
+	raise(sig);
+}
+
+void term_set_tty(int term)
+{
+	struct termios orig_term;
+	int master, slave;
+	char new_pty[PATH_MAX];
+
+	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
+		die("unable to save initial standard input settings");
+
+	orig_term.c_lflag &= ~(ICANON | ECHO | ISIG);
+
+	if (openpty(&master, &slave, new_pty, &orig_term, NULL) < 0)
+		return;
+
+	close(slave);
+
+	pr_info("Assigned terminal %d to pty %s\n", term, new_pty);
+
+	term_fds[term][TERM_FD_IN] = term_fds[term][TERM_FD_OUT] = master;
+}
+
+void term_init(void)
+{
+	struct termios term;
+	int i;
+
+	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
+		die("unable to save initial standard input settings");
+
+	term = orig_term;
+	term.c_lflag &= ~(ICANON | ECHO | ISIG);
+	tcsetattr(STDIN_FILENO, TCSANOW, &term);
+
+	for (i = 0; i < 4; i++)
+		if (term_fds[i][TERM_FD_IN] == 0) {
+			term_fds[i][TERM_FD_IN] = STDIN_FILENO;
+			term_fds[i][TERM_FD_OUT] = STDOUT_FILENO;
+		}
+
+	signal(SIGTERM, term_sig_cleanup);
+	atexit(term_cleanup);
+}
diff --git a/tools/kvm/tests/Makefile b/tools/kvm/tests/Makefile
new file mode 100644
index 0000000..cad14ec
--- /dev/null
+++ b/tools/kvm/tests/Makefile
@@ -0,0 +1,19 @@
+all: kernel pit boot
+
+kernel:
+	$(MAKE) -C kernel
+.PHONY: kernel
+
+pit:
+	$(MAKE) -C pit
+.PHONY: pit
+
+boot:
+	$(MAKE) -C boot
+.PHONY: boot
+
+clean:
+	$(MAKE) -C kernel clean
+	$(MAKE) -C pit clean
+	$(MAKE) -C boot clean
+.PHONY: clean
diff --git a/tools/kvm/tests/boot/Makefile b/tools/kvm/tests/boot/Makefile
new file mode 100644
index 0000000..40cba68
--- /dev/null
+++ b/tools/kvm/tests/boot/Makefile
@@ -0,0 +1,13 @@
+NAME	:= init
+
+OBJ	:= $(NAME).o
+
+all: $(.o)
+	rm -rf rootfs
+	mkdir rootfs
+	gcc -static init.c -o rootfs/init
+	mkisofs rootfs > boot_test.iso
+
+clean:
+	rm -rf rootfs boot_test.iso
+.PHONY: clean
diff --git a/tools/kvm/tests/boot/init.c b/tools/kvm/tests/boot/init.c
new file mode 100644
index 0000000..094f8ba
--- /dev/null
+++ b/tools/kvm/tests/boot/init.c
@@ -0,0 +1,11 @@
+#include <linux/reboot.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+	puts("hello, KVM guest!\r");
+
+	reboot(LINUX_REBOOT_CMD_RESTART);
+
+	return 0;
+}
diff --git a/tools/kvm/tests/kernel/.gitignore b/tools/kvm/tests/kernel/.gitignore
new file mode 100644
index 0000000..d0cd209
--- /dev/null
+++ b/tools/kvm/tests/kernel/.gitignore
@@ -0,0 +1,2 @@
+kernel.bin
+kernel.elf
diff --git a/tools/kvm/tests/kernel/Makefile b/tools/kvm/tests/kernel/Makefile
new file mode 100644
index 0000000..c7dd8da
--- /dev/null
+++ b/tools/kvm/tests/kernel/Makefile
@@ -0,0 +1,20 @@
+NAME	:= kernel
+
+BIN	:= $(NAME).bin
+ELF	:= $(NAME).elf
+OBJ	:= $(NAME).o
+
+all: $(BIN)
+
+$(BIN): $(ELF)
+	objcopy -O binary $< $@
+
+$(ELF): $(OBJ)
+	ld -Ttext=0x00 -nostdlib -static $< -o $@
+
+%.o: %.S
+	gcc -nostdinc -c $< -o $@
+
+clean:
+	rm -f $(BIN) $(ELF) $(OBJ)
+.PHONY: clean
diff --git a/tools/kvm/tests/kernel/README b/tools/kvm/tests/kernel/README
new file mode 100644
index 0000000..2923777
--- /dev/null
+++ b/tools/kvm/tests/kernel/README
@@ -0,0 +1,16 @@
+Compiling
+---------
+
+You can simply type:
+
+  $ make
+
+to build a 16-bit binary that uses the i8086 instruction set.
+
+Disassembling
+-------------
+
+Use the "-m i8086" command line option with objdump to make sure it knows we're
+dealing with i8086 instruction set:
+
+  $ objdump -d -m i8086 i8086.elf
diff --git a/tools/kvm/tests/kernel/kernel.S b/tools/kvm/tests/kernel/kernel.S
new file mode 100644
index 0000000..2824b64
--- /dev/null
+++ b/tools/kvm/tests/kernel/kernel.S
@@ -0,0 +1,8 @@
+	.code16gcc
+	.text
+	.globl  _start
+	.type   _start, @function
+_start:
+	# "This is probably the largest possible kernel that is bug free." -- Avi Kivity
+	1:
+	jmp 1b
diff --git a/tools/kvm/tests/pit/.gitignore b/tools/kvm/tests/pit/.gitignore
new file mode 100644
index 0000000..43f0aa8
--- /dev/null
+++ b/tools/kvm/tests/pit/.gitignore
@@ -0,0 +1,2 @@
+*.bin
+*.elf
diff --git a/tools/kvm/tests/pit/Makefile b/tools/kvm/tests/pit/Makefile
new file mode 100644
index 0000000..2fae9b2
--- /dev/null
+++ b/tools/kvm/tests/pit/Makefile
@@ -0,0 +1,20 @@
+NAME	:= tick
+
+BIN	:= $(NAME).bin
+ELF	:= $(NAME).elf
+OBJ	:= $(NAME).o
+
+all: $(BIN)
+
+$(BIN): $(ELF)
+	objcopy -O binary $< $@
+
+$(ELF): $(OBJ)
+	ld -Ttext=0x00 -nostdlib -static $< -o $@
+
+%.o: %.S
+	gcc -nostdinc -c $< -o $@
+
+clean:
+	rm -f $(BIN) $(ELF) $(OBJ)
+.PHONY: clean
diff --git a/tools/kvm/tests/pit/README b/tools/kvm/tests/pit/README
new file mode 100644
index 0000000..2923777
--- /dev/null
+++ b/tools/kvm/tests/pit/README
@@ -0,0 +1,16 @@
+Compiling
+---------
+
+You can simply type:
+
+  $ make
+
+to build a 16-bit binary that uses the i8086 instruction set.
+
+Disassembling
+-------------
+
+Use the "-m i8086" command line option with objdump to make sure it knows we're
+dealing with i8086 instruction set:
+
+  $ objdump -d -m i8086 i8086.elf
diff --git a/tools/kvm/tests/pit/tick.S b/tools/kvm/tests/pit/tick.S
new file mode 100644
index 0000000..b9e5a80
--- /dev/null
+++ b/tools/kvm/tests/pit/tick.S
@@ -0,0 +1,109 @@
+#define IO_PIC		0x20
+#define IRQ_OFFSET	32
+#define IO_PIT		0x40
+#define TIMER_FREQ	1193182
+#define TIMER_DIV(x)	((TIMER_FREQ+(x)/2)/(x))
+
+/*
+ * hpa noted:
+ *
+ * 0xe0..0xef are "motherboard specific", but 0xe9 is
+ * used for Bochs debugging and 0xed is the Phoenix-reserved
+ * delay port
+ */
+#define DBG_PORT	0xe0
+
+#define TEST_COUNT	0x0200
+
+	.code16gcc
+	.text
+	.globl	_start
+	.type	_start, @function
+_start:
+/*
+ * fill up noop handlers
+ */
+	xorw	%ax, %ax
+	xorw	%di, %di
+	movw	%ax, %es
+	movw	$256, %cx
+fill_noop_idt:
+	movw	$noop_handler, %es:(%di)
+	movw	%cs, %es:2(%di)
+	add	$4, %di
+	loop	fill_noop_idt
+
+set_idt:
+	movw	$timer_isr, %es:(IRQ_OFFSET*4)
+	movw	%cs, %es:(IRQ_OFFSET*4+2)
+
+set_pic:
+	# ICW1
+	mov	$0x11, %al
+	mov	$(IO_PIC), %dx
+	out	%al,%dx
+	# ICW2
+	mov	$(IRQ_OFFSET), %al
+	mov	$(IO_PIC+1), %dx
+	out	%al, %dx
+	# ICW3
+	mov	$0x00, %al
+	mov	$(IO_PIC+1), %dx
+	out	%al, %dx
+	# ICW4
+	mov	$0x3, %al
+	mov	$(IO_PIC+1), %dx
+	out	%al, %dx
+
+set_pit:
+	# set 8254 mode
+	mov	$(IO_PIT+3), %dx
+	mov	$0x34, %al
+	outb	%al, %dx
+	# set 8254 freq 1KHz
+	mov	$(IO_PIT), %dx
+	movb	$(TIMER_DIV(1000) % 256), %al
+	outb	%al, %dx
+	movb	$(TIMER_DIV(1000) / 256), %al
+	outb	%al, %dx
+
+enable_irq0:
+	mov	$0xfe, %al
+	mov	$(IO_PIC+1), %dx
+	out	%al, %dx
+	sti
+loop:
+	1:
+	jmp	1b
+
+test_ok:
+	mov	$0x3f8,%dx
+	cs lea	msg2, %si
+	mov	$(msg2_end-msg2), %cx
+	cs rep/outsb
+
+	/* not a valid port to force exit */
+	outb	%al, $DBG_PORT
+
+timer_isr:
+	cli
+	pushaw
+	pushfw
+	mov	$0x3f8,%dx
+	mov	$0x2e, %al	# .
+	out	%al,%dx
+	decw	count
+	jz	test_ok
+	popfw
+	popaw
+	iretw
+
+noop_handler:
+	iretw
+
+count:
+	.word	TEST_COUNT
+
+msg2:
+	.asciz "\nTest OK\n"
+msg2_end:
diff --git a/tools/kvm/ui/sdl.c b/tools/kvm/ui/sdl.c
new file mode 100644
index 0000000..ac7f013
--- /dev/null
+++ b/tools/kvm/ui/sdl.c
@@ -0,0 +1,280 @@
+#include "kvm/sdl.h"
+
+#include "kvm/framebuffer.h"
+#include "kvm/i8042.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/kvm-cpu.h"
+
+#include <SDL/SDL.h>
+#include <pthread.h>
+#include <signal.h>
+
+#define FRAME_RATE		25
+
+#define SCANCODE_UNKNOWN      0
+#define SCANCODE_NORMAL       1
+#define SCANCODE_ESCAPED      2
+#define SCANCODE_KEY_PAUSE    3
+#define SCANCODE_KEY_PRNTSCRN 4
+
+struct set2_scancode {
+	u8 code;
+	u8 type;
+};
+
+#define DEFINE_SC(_code) {\
+	.code = _code,\
+	.type = SCANCODE_NORMAL,\
+}
+
+/* escaped scancodes */
+#define DEFINE_ESC(_code) {\
+	.code = _code,\
+	.type = SCANCODE_ESCAPED,\
+}
+
+static const struct set2_scancode const keymap[256] = {
+	[9]	= DEFINE_SC(0x76),	/* <esc> */
+	[10]	= DEFINE_SC(0x16),	/* 1 */
+	[11]	= DEFINE_SC(0x1e),	/* 2 */
+	[12]	= DEFINE_SC(0x26),	/* 3 */
+	[13]	= DEFINE_SC(0x25),	/* 4 */
+	[14]	= DEFINE_SC(0x2e),	/* 5 */
+	[15]	= DEFINE_SC(0x36),	/* 6 */
+	[16]	= DEFINE_SC(0x3d),	/* 7 */
+	[17]	= DEFINE_SC(0x3e),	/* 8 */
+	[18]	= DEFINE_SC(0x46),	/* 9 */
+	[19]	= DEFINE_SC(0x45),	/* 9 */
+	[20]	= DEFINE_SC(0x4e),	/* - */
+	[21]	= DEFINE_SC(0x55),	/* + */
+	[22]	= DEFINE_SC(0x66),	/* <backspace> */
+	[23]	= DEFINE_SC(0x0d),	/* <tab> */
+	[24]	= DEFINE_SC(0x15),	/* q */
+	[25]	= DEFINE_SC(0x1d),	/* w */
+	[26]	= DEFINE_SC(0x24),	/* e */
+	[27]	= DEFINE_SC(0x2d),	/* r */
+	[28]	= DEFINE_SC(0x2c),	/* t */
+	[29]	= DEFINE_SC(0x35),	/* y */
+	[30]	= DEFINE_SC(0x3c),	/* u */
+	[31]	= DEFINE_SC(0x43),	/* i */
+	[32]	= DEFINE_SC(0x44),	/* o */
+	[33]	= DEFINE_SC(0x4d),	/* p */
+	[34]	= DEFINE_SC(0x54),	/* [ */
+	[35]	= DEFINE_SC(0x5b),	/* ] */
+	[36]	= DEFINE_SC(0x5a),	/* <enter> */
+	[37]	= DEFINE_SC(0x14),	/* <left ctrl> */
+	[38]	= DEFINE_SC(0x1c),	/* a */
+	[39]	= DEFINE_SC(0x1b),	/* s */
+	[40]	= DEFINE_SC(0x23),	/* d */
+	[41]	= DEFINE_SC(0x2b),	/* f */
+	[42]	= DEFINE_SC(0x34),	/* g */
+	[43]	= DEFINE_SC(0x33),	/* h */
+	[44]	= DEFINE_SC(0x3b),	/* j */
+	[45]	= DEFINE_SC(0x42),	/* k */
+	[46]	= DEFINE_SC(0x4b),	/* l */
+	[47]	= DEFINE_SC(0x4c),	/* ; */
+	[48]	= DEFINE_SC(0x52),	/* ' */
+	[49]	= DEFINE_SC(0x0e),	/* ` */
+	[50]	= DEFINE_SC(0x12),	/* <left shift> */
+	[51]	= DEFINE_SC(0x5d),	/* \ */
+	[52]	= DEFINE_SC(0x1a),	/* z */
+	[53]	= DEFINE_SC(0x22),	/* x */
+	[54]	= DEFINE_SC(0x21),	/* c */
+	[55]	= DEFINE_SC(0x2a),	/* v */
+	[56]	= DEFINE_SC(0x32),	/* b */
+	[57]	= DEFINE_SC(0x31),	/* n */
+	[58]	= DEFINE_SC(0x3a),	/* m */
+	[59]	= DEFINE_SC(0x41),	/* < */
+	[60]	= DEFINE_SC(0x49),	/* > */
+	[61]	= DEFINE_SC(0x4a),	/* / */
+	[62]	= DEFINE_SC(0x59),	/* <right shift> */
+	[63]	= DEFINE_SC(0x7c),	/* keypad * */
+	[64]	= DEFINE_SC(0x11),	/* <left alt> */
+	[65]	= DEFINE_SC(0x29),	/* <space> */
+
+	[67]	= DEFINE_SC(0x05),	/* <F1> */
+	[68]	= DEFINE_SC(0x06),	/* <F2> */
+	[69]	= DEFINE_SC(0x04),	/* <F3> */
+	[70]	= DEFINE_SC(0x0c),	/* <F4> */
+	[71]	= DEFINE_SC(0x03),	/* <F5> */
+	[72]	= DEFINE_SC(0x0b),	/* <F6> */
+	[73]	= DEFINE_SC(0x83),	/* <F7> */
+	[74]	= DEFINE_SC(0x0a),	/* <F8> */
+	[75]	= DEFINE_SC(0x01),	/* <F9> */
+	[76]	= DEFINE_SC(0x09),	/* <F10> */
+
+	[79]	= DEFINE_SC(0x6c),	/* keypad 7 */
+	[80]	= DEFINE_SC(0x75),	/* keypad 8 */
+	[81]	= DEFINE_SC(0x7d),	/* keypad 9 */
+	[82]	= DEFINE_SC(0x7b),	/* keypad - */
+	[83]	= DEFINE_SC(0x6b),	/* keypad 4 */
+	[84]	= DEFINE_SC(0x73),	/* keypad 5 */
+	[85]	= DEFINE_SC(0x74),	/* keypad 6 */
+	[86]	= DEFINE_SC(0x79),	/* keypad + */
+	[87]	= DEFINE_SC(0x69),	/* keypad 1 */
+	[88]	= DEFINE_SC(0x72),	/* keypad 2 */
+	[89]	= DEFINE_SC(0x7a),	/* keypad 3 */
+	[90]	= DEFINE_SC(0x70),	/* keypad 0 */
+	[91]	= DEFINE_SC(0x71),	/* keypad . */
+
+	[94]	= DEFINE_SC(0x61),	/* <INT 1> */
+	[95]	= DEFINE_SC(0x78),	/* <F11> */
+	[96]	= DEFINE_SC(0x07),	/* <F12> */
+
+	[104]	= DEFINE_ESC(0x5a),	/* keypad <enter> */
+	[105]	= DEFINE_ESC(0x14),	/* <right ctrl> */
+	[106]	= DEFINE_ESC(0x4a),	/* keypad / */
+	[108]	= DEFINE_ESC(0x11),	/* <right alt> */
+	[110]	= DEFINE_ESC(0x6c),	/* <home> */
+	[111]	= DEFINE_ESC(0x75),	/* <up> */
+	[112]	= DEFINE_ESC(0x7d),	/* <pag up> */
+	[113]	= DEFINE_ESC(0x6b),	/* <left> */
+	[114]	= DEFINE_ESC(0x74),	/* <right> */
+	[115]	= DEFINE_ESC(0x69),	/* <end> */
+	[116]	= DEFINE_ESC(0x72),	/* <down> */
+	[117]	= DEFINE_ESC(0x7a),	/* <pag down> */
+	[118]	= DEFINE_ESC(0x70),	/* <ins> */
+	[119]	= DEFINE_ESC(0x71),	/* <delete> */
+};
+
+static const struct set2_scancode *to_code(u8 scancode)
+{
+	return &keymap[scancode];
+}
+
+static void key_press(const struct set2_scancode *sc)
+{
+	switch (sc->type) {
+	case SCANCODE_ESCAPED:
+		kbd_queue(0xe0);
+		/* fallthrough */
+	case SCANCODE_NORMAL:
+		kbd_queue(sc->code);
+		break;
+	case SCANCODE_KEY_PAUSE:
+		kbd_queue(0xe1);
+		kbd_queue(0x14);
+		kbd_queue(0x77);
+		kbd_queue(0xe1);
+		kbd_queue(0xf0);
+		kbd_queue(0x14);
+		kbd_queue(0x77);
+		break;
+	case SCANCODE_KEY_PRNTSCRN:
+		kbd_queue(0xe0);
+		kbd_queue(0x12);
+		kbd_queue(0xe0);
+		kbd_queue(0x7c);
+		break;
+	}
+}
+
+static void key_release(const struct set2_scancode *sc)
+{
+	switch (sc->type) {
+	case SCANCODE_ESCAPED:
+		kbd_queue(0xe0);
+		/* fallthrough */
+	case SCANCODE_NORMAL:
+		kbd_queue(0xf0);
+		kbd_queue(sc->code);
+		break;
+	case SCANCODE_KEY_PAUSE:
+		/* nothing to do */
+		break;
+	case SCANCODE_KEY_PRNTSCRN:
+		kbd_queue(0xe0);
+		kbd_queue(0xf0);
+		kbd_queue(0x7c);
+		kbd_queue(0xe0);
+		kbd_queue(0xf0);
+		kbd_queue(0x12);
+		break;
+	}
+}
+
+static void *sdl__thread(void *p)
+{
+	Uint32 rmask, gmask, bmask, amask;
+	struct framebuffer *fb = p;
+	SDL_Surface *guest_screen;
+	SDL_Surface *screen;
+	SDL_Event ev;
+	Uint32 flags;
+
+	if (SDL_Init(SDL_INIT_VIDEO) != 0)
+		die("Unable to initialize SDL");
+
+	rmask = 0x000000ff;
+	gmask = 0x0000ff00;
+	bmask = 0x00ff0000;
+	amask = 0x00000000;
+
+	guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask);
+	if (!guest_screen)
+		die("Unable to create SDL RBG surface");
+
+	flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL | SDL_DOUBLEBUF;
+
+	SDL_WM_SetCaption("KVM tool", "KVM tool");
+
+	screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags);
+	if (!screen)
+		die("Unable to set SDL video mode");
+
+	SDL_EnableKeyRepeat(200, 50);
+
+	for (;;) {
+		SDL_BlitSurface(guest_screen, NULL, screen, NULL);
+		SDL_Flip(screen);
+
+		while (SDL_PollEvent(&ev)) {
+			switch (ev.type) {
+			case SDL_KEYDOWN: {
+				const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
+				if (sc->type == SCANCODE_UNKNOWN) {
+					pr_warning("key '%d' not found in keymap", ev.key.keysym.scancode);
+					break;
+				}
+				key_press(sc);
+				break;
+			}
+			case SDL_KEYUP: {
+				const struct set2_scancode *sc = to_code(ev.key.keysym.scancode);
+				if (sc->type == SCANCODE_UNKNOWN)
+					break;
+				key_release(sc);
+				break;
+			}
+			case SDL_QUIT:
+				goto exit;
+			}
+		}
+
+		SDL_Delay(1000 / FRAME_RATE);
+	}
+exit:
+	kvm_cpu__reboot();
+
+	return NULL;
+}
+
+static int sdl__start(struct framebuffer *fb)
+{
+	pthread_t thread;
+
+	if (pthread_create(&thread, NULL, sdl__thread, fb) != 0)
+		return -1;
+
+	return 0;
+}
+
+static struct fb_target_operations sdl_ops = {
+	.start			= sdl__start,
+};
+
+void sdl__init(struct framebuffer *fb)
+{
+	fb__attach(fb, &sdl_ops);
+}
diff --git a/tools/kvm/ui/vnc.c b/tools/kvm/ui/vnc.c
new file mode 100644
index 0000000..d760492
--- /dev/null
+++ b/tools/kvm/ui/vnc.c
@@ -0,0 +1,218 @@
+#include "kvm/vnc.h"
+
+#include "kvm/framebuffer.h"
+#include "kvm/i8042.h"
+
+#include <linux/types.h>
+#include <rfb/keysym.h>
+#include <rfb/rfb.h>
+#include <pthread.h>
+
+#define VESA_QUEUE_SIZE		128
+#define VESA_IRQ		14
+
+/*
+ * This "6000" value is pretty much the result of experimentation
+ * It seems that around this value, things update pretty smoothly
+ */
+#define VESA_UPDATE_TIME	6000
+
+/*
+ * We can map the letters and numbers without a fuss,
+ * but the other characters not so much.
+ */
+static char letters[26] = {
+	0x1c, 0x32, 0x21, 0x23, 0x24, /* a-e */
+	0x2b, 0x34, 0x33, 0x43, 0x3b, /* f-j */
+	0x42, 0x4b, 0x3a, 0x31, 0x44, /* k-o */
+	0x4d, 0x15, 0x2d, 0x1b, 0x2c, /* p-t */
+	0x3c, 0x2a, 0x1d, 0x22, 0x35, /* u-y */
+	0x1a,
+};
+
+static char num[10] = {
+	0x45, 0x16, 0x1e, 0x26, 0x2e, 0x23, 0x36, 0x3d, 0x3e, 0x46,
+};
+
+/*
+ * This is called when the VNC server receives a key event
+ * The reason this function is such a beast is that we have
+ * to convert from ASCII characters (which is what VNC gets)
+ * to PC keyboard scancodes, which is what Linux expects to
+ * get from its keyboard. ASCII and the scancode set don't
+ * really seem to mesh in any good way beyond some basics with
+ * the letters and numbers.
+ */
+static void kbd_handle_key(rfbBool down, rfbKeySym key, rfbClientPtr cl)
+{
+	char tosend = 0;
+
+	if (key >= 0x41 && key <= 0x5a)
+		key += 0x20; /* convert to lowercase */
+
+	if (key >= 0x61 && key <= 0x7a) /* a-z */
+		tosend = letters[key - 0x61];
+
+	if (key >= 0x30 && key <= 0x39)
+		tosend = num[key - 0x30];
+
+	switch (key) {
+	case XK_Insert:		kbd_queue(0xe0);	tosend = 0x70;	break;
+	case XK_Delete:		kbd_queue(0xe0);	tosend = 0x71;	break;
+	case XK_Up:		kbd_queue(0xe0);	tosend = 0x75;	break;
+	case XK_Down:		kbd_queue(0xe0);	tosend = 0x72;	break;
+	case XK_Left:		kbd_queue(0xe0);	tosend = 0x6b;	break;
+	case XK_Right:		kbd_queue(0xe0);	tosend = 0x74;	break;
+	case XK_Page_Up:	kbd_queue(0xe0);	tosend = 0x7d;	break;
+	case XK_Page_Down:	kbd_queue(0xe0);	tosend = 0x7a;	break;
+	case XK_Home:		kbd_queue(0xe0);	tosend = 0x6c;	break;
+	case XK_BackSpace:	tosend = 0x66;		break;
+	case XK_Tab:		tosend = 0x0d;		break;
+	case XK_Return:		tosend = 0x5a;		break;
+	case XK_Escape:		tosend = 0x76;		break;
+	case XK_End:		tosend = 0x69;		break;
+	case XK_Shift_L:	tosend = 0x12;		break;
+	case XK_Shift_R:	tosend = 0x59;		break;
+	case XK_Control_R:	kbd_queue(0xe0);
+	case XK_Control_L:	tosend = 0x14;		break;
+	case XK_Alt_R:		kbd_queue(0xe0);
+	case XK_Alt_L:		tosend = 0x11;		break;
+	case XK_quoteleft:	tosend = 0x0e;		break;
+	case XK_minus:		tosend = 0x4e;		break;
+	case XK_equal:		tosend = 0x55;		break;
+	case XK_bracketleft:	tosend = 0x54;		break;
+	case XK_bracketright:	tosend = 0x5b;		break;
+	case XK_backslash:	tosend = 0x5d;		break;
+	case XK_Caps_Lock:	tosend = 0x58;		break;
+	case XK_semicolon:	tosend = 0x4c;		break;
+	case XK_quoteright:	tosend = 0x52;		break;
+	case XK_comma:		tosend = 0x41;		break;
+	case XK_period:		tosend = 0x49;		break;
+	case XK_slash:		tosend = 0x4a;		break;
+	case XK_space:		tosend = 0x29;		break;
+
+	/*
+	 * This is where I handle the shifted characters.
+	 * They don't really map nicely the way A-Z maps to a-z,
+	 * so I'm doing it manually
+	 */
+	case XK_exclam:		tosend = 0x16;		break;
+	case XK_quotedbl:	tosend = 0x52;		break;
+	case XK_numbersign:	tosend = 0x26;		break;
+	case XK_dollar:		tosend = 0x25;		break;
+	case XK_percent:	tosend = 0x2e;		break;
+	case XK_ampersand:	tosend = 0x3d;		break;
+	case XK_parenleft:	tosend = 0x46;		break;
+	case XK_parenright:	tosend = 0x45;		break;
+	case XK_asterisk:	tosend = 0x3e;		break;
+	case XK_plus:		tosend = 0x55;		break;
+	case XK_colon:		tosend = 0x4c;		break;
+	case XK_less:		tosend = 0x41;		break;
+	case XK_greater:	tosend = 0x49;		break;
+	case XK_question:	tosend = 0x4a;		break;
+	case XK_at:		tosend = 0x1e;		break;
+	case XK_asciicircum:	tosend = 0x36;		break;
+	case XK_underscore:	tosend = 0x4e;		break;
+	case XK_braceleft:	tosend = 0x54;		break;
+	case XK_braceright:	tosend = 0x5b;		break;
+	case XK_bar:		tosend = 0x5d;		break;
+	case XK_asciitilde:	tosend = 0x0e;		break;
+	default:		break;
+	}
+
+	/*
+	 * If this is a "key up" event (the user has released the key, we
+	 * need to send 0xf0 first.
+	 */
+	if (!down && tosend != 0x0)
+		kbd_queue(0xf0);
+
+	if (tosend)
+		kbd_queue(tosend);
+}
+
+/* The previous X and Y coordinates of the mouse */
+static int xlast, ylast = -1;
+
+/*
+ * This function is called by the VNC server whenever a mouse event occurs.
+ */
+static void kbd_handle_ptr(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+	int dx, dy;
+	char b1 = 0x8;
+
+	/* The VNC mask and the PS/2 button encoding are the same */
+	b1 |= buttonMask;
+
+	if (xlast >= 0 && ylast >= 0) {
+		/* The PS/2 mouse sends deltas, not absolutes */
+		dx = x - xlast;
+		dy = ylast - y;
+
+		/* Set overflow bits if needed */
+		if (dy > 255)
+			b1 |= 0x80;
+		if (dx > 255)
+			b1 |= 0x40;
+
+		/* Set negative bits if needed */
+		if (dy < 0)
+			b1 |= 0x20;
+		if (dx < 0)
+			b1 |= 0x10;
+
+		mouse_queue(b1);
+		mouse_queue(dx);
+		mouse_queue(dy);
+	}
+
+	xlast = x;
+	ylast = y;
+	rfbDefaultPtrAddEvent(buttonMask, x, y, cl);
+}
+
+static void *vnc__thread(void *p)
+{
+	struct framebuffer *fb = p;
+	/*
+	 * Make a fake argc and argv because the getscreen function
+	 * seems to want it.
+	 */
+	char argv[1][1] = {{0}};
+	int argc = 1;
+
+	rfbScreenInfoPtr server;
+
+	server = rfbGetScreen(&argc, (char **) argv, fb->width, fb->height, 8, 3, 4);
+	server->frameBuffer		= fb->mem;
+	server->alwaysShared		= TRUE;
+	server->kbdAddEvent		= kbd_handle_key;
+	server->ptrAddEvent		= kbd_handle_ptr;
+	rfbInitServer(server);
+
+	while (rfbIsActive(server)) {
+		rfbMarkRectAsModified(server, 0, 0, fb->width, fb->height);
+		rfbProcessEvents(server, server->deferUpdateTime * VESA_UPDATE_TIME);
+	}
+	return NULL;
+}
+
+static int vnc__start(struct framebuffer *fb)
+{
+	pthread_t thread;
+
+	if (pthread_create(&thread, NULL, vnc__thread, fb) != 0)
+		return -1;
+
+	return 0;
+}
+
+static struct fb_target_operations vnc_ops = {
+	.start			= vnc__start,
+};
+
+void vnc__init(struct framebuffer *fb)
+{
+	fb__attach(fb, &vnc_ops);
+}
diff --git a/tools/kvm/util/KVMTOOLS-VERSION-GEN b/tools/kvm/util/KVMTOOLS-VERSION-GEN
new file mode 100755
index 0000000..1af9d6c
--- /dev/null
+++ b/tools/kvm/util/KVMTOOLS-VERSION-GEN
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+if [ $# -eq 1 ]  ; then
+	OUTPUT=$1
+fi
+
+GVF=${OUTPUT}KVMTOOLS-VERSION-FILE
+
+LF='
+'
+
+# First check if there is a .git to get the version from git describe
+# otherwise try to get the version from the kernel makefile
+if test -d ../../.git -o -f ../../.git &&
+	VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+	case "$VN" in
+	*$LF*) (exit 1) ;;
+	v[0-9]*)
+		git update-index -q --refresh
+		test -z "$(git diff-index --name-only HEAD --)" ||
+		VN="$VN-dirty" ;;
+	esac
+then
+	VN=$(echo "$VN" | sed -e 's/-/./g');
+else
+	VN=$(MAKEFLAGS= make -sC ../.. kernelversion)
+fi
+
+VN=$(expr "$VN" : v*'\(.*\)')
+
+if test -r $GVF
+then
+	VC=$(sed -e 's/^KVMTOOLS_VERSION = //' <$GVF)
+else
+	VC=unset
+fi
+test "$VN" = "$VC" || {
+	echo >&2 "KVMTOOLS_VERSION = $VN"
+	echo "KVMTOOLS_VERSION = $VN" >$GVF
+}
diff --git a/tools/kvm/util/generate-cmdlist.sh b/tools/kvm/util/generate-cmdlist.sh
new file mode 100755
index 0000000..c8be0bd
--- /dev/null
+++ b/tools/kvm/util/generate-cmdlist.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+echo "/* Automatically generated by $0 */
+struct cmdname_help
+{
+    char name[16];
+    char help[80];
+};
+
+static struct cmdname_help common_cmds[] = {"
+
+sed -n 's/^lkvm-\([^ \t]*\).*common/\1/p' command-list.txt |
+while read cmd
+do
+	 # TODO following sed command should be fixed
+     sed -n '/^NAME/,/^lkvm-'"$cmd"'/ {
+		 /NAME/d
+		 /--/d
+		 s/.*kvm-'"$cmd"' - \(.*\)/  {"'"$cmd"'", "\1"},/
+	     p
+	 }' "Documentation/kvm-$cmd.txt"
+done
+echo "};"
diff --git a/tools/kvm/util/kvm-ifup-vbr0 b/tools/kvm/util/kvm-ifup-vbr0
new file mode 100755
index 0000000..a91c37f
--- /dev/null
+++ b/tools/kvm/util/kvm-ifup-vbr0
@@ -0,0 +1,6 @@
+#!/bin/sh
+switch=vbr0
+/sbin/ifconfig $1 0.0.0.0 up
+/usr/sbin/brctl addif ${switch} $1
+/usr/sbin/brctl setfd ${switch} 0
+/usr/sbin/brctl stp ${switch} off
diff --git a/tools/kvm/util/parse-options.c b/tools/kvm/util/parse-options.c
new file mode 100644
index 0000000..9a1bbee
--- /dev/null
+++ b/tools/kvm/util/parse-options.c
@@ -0,0 +1,577 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdbool.h>
+
+/* user defined includes */
+#include <linux/types.h>
+#include <kvm/util.h>
+#include <kvm/parse-options.h>
+#include <kvm/strbuf.h>
+
+#define OPT_SHORT 1
+#define OPT_UNSET 2
+
+static int opterror(const struct option *opt, const char *reason, int flags)
+{
+	if (flags & OPT_SHORT)
+		return pr_err("switch `%c' %s", opt->short_name, reason);
+	if (flags & OPT_UNSET)
+		return pr_err("option `no-%s' %s", opt->long_name, reason);
+	return pr_err("option `%s' %s", opt->long_name, reason);
+}
+
+static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
+		int flags, const char **arg)
+{
+	if (p->opt) {
+		*arg = p->opt;
+		p->opt = NULL;
+	} else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
+				**(p->argv + 1) == '-')) {
+		*arg = (const char *)opt->defval;
+	} else if (p->argc > 1) {
+		p->argc--;
+		*arg = *++p->argv;
+	} else
+		return opterror(opt, "requires a value", flags);
+	return 0;
+}
+
+static int readnum(const struct option *opt, int flags,
+		   const char *str, char **end)
+{
+	switch (opt->type) {
+	case OPTION_INTEGER:
+		*(int *)opt->value = strtol(str, end, 0);
+		break;
+	case OPTION_UINTEGER:
+		*(unsigned int *)opt->value = strtol(str, end, 0);
+		break;
+	case OPTION_LONG:
+		*(long *)opt->value = strtol(str, end, 0);
+		break;
+	case OPTION_U64:
+		*(u64 *)opt->value = strtoull(str, end, 0);
+		break;
+	default:
+		return opterror(opt, "invalid numeric conversion", flags);
+	}
+
+	return 0;
+}
+
+static int get_value(struct parse_opt_ctx_t *p,
+		const struct option *opt, int flags)
+{
+	const char *s, *arg = NULL;
+	const int unset = flags & OPT_UNSET;
+
+	if (unset && p->opt)
+		return opterror(opt, "takes no value", flags);
+	if (unset && (opt->flags & PARSE_OPT_NONEG))
+		return opterror(opt, "isn't available", flags);
+
+	if (!(flags & OPT_SHORT) && p->opt) {
+		switch (opt->type) {
+		case OPTION_CALLBACK:
+			if (!(opt->flags & PARSE_OPT_NOARG))
+				break;
+		/* FALLTHROUGH */
+		case OPTION_BOOLEAN:
+		case OPTION_INCR:
+		case OPTION_BIT:
+		case OPTION_SET_UINT:
+		case OPTION_SET_PTR:
+			return opterror(opt, "takes no value", flags);
+		case OPTION_END:
+		case OPTION_ARGUMENT:
+		case OPTION_GROUP:
+		case OPTION_STRING:
+		case OPTION_INTEGER:
+		case OPTION_UINTEGER:
+		case OPTION_LONG:
+		case OPTION_U64:
+		default:
+			break;
+		}
+	}
+
+	switch (opt->type) {
+	case OPTION_BIT:
+		if (unset)
+			*(int *)opt->value &= ~opt->defval;
+		else
+			*(int *)opt->value |= opt->defval;
+		return 0;
+
+	case OPTION_BOOLEAN:
+		*(bool *)opt->value = unset ? false : true;
+		return 0;
+
+	case OPTION_INCR:
+		*(int *)opt->value = unset ? 0 : *(int *)opt->value + 1;
+		return 0;
+
+	case OPTION_SET_UINT:
+		*(unsigned int *)opt->value = unset ? 0 : opt->defval;
+		return 0;
+
+	case OPTION_SET_PTR:
+		*(void **)opt->value = unset ? NULL : (void *)opt->defval;
+		return 0;
+
+	case OPTION_STRING:
+		if (unset)
+			*(const char **)opt->value = NULL;
+		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			*(const char **)opt->value = (const char *)opt->defval;
+		else
+			return get_arg(p, opt, flags,
+					(const char **)opt->value);
+		return 0;
+
+	case OPTION_CALLBACK:
+		if (unset)
+			return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
+		if (opt->flags & PARSE_OPT_NOARG)
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
+
+	case OPTION_INTEGER:
+		if (unset) {
+			*(int *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(int *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return readnum(opt, flags, arg, (char **)&s);
+
+	case OPTION_UINTEGER:
+		if (unset) {
+			*(unsigned int *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(unsigned int *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return readnum(opt, flags, arg, (char **)&s);
+
+	case OPTION_LONG:
+		if (unset) {
+			*(long *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(long *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return readnum(opt, flags, arg, (char **)&s);
+
+	case OPTION_U64:
+		if (unset) {
+			*(u64 *)opt->value = 0;
+			return 0;
+		}
+		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+			*(u64 *)opt->value = opt->defval;
+			return 0;
+		}
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return readnum(opt, flags, arg, (char **)&s);
+
+	case OPTION_END:
+	case OPTION_ARGUMENT:
+	case OPTION_GROUP:
+	default:
+		die("should not happen, someone must be hit on the forehead");
+	}
+}
+
+#define USAGE_OPTS_WIDTH 24
+#define USAGE_GAP         2
+
+static int usage_with_options_internal(const char * const *usagestr,
+		const struct option *opts, int full)
+{
+	if (!usagestr)
+		return PARSE_OPT_HELP;
+
+	fprintf(stderr, "\n usage: %s\n", *usagestr++);
+	while (*usagestr && **usagestr)
+		fprintf(stderr, "    or: %s\n", *usagestr++);
+	while (*usagestr) {
+		fprintf(stderr, "%s%s\n",
+				**usagestr ? "    " : "",
+				*usagestr);
+		usagestr++;
+	}
+
+	if (opts->type != OPTION_GROUP)
+		fputc('\n', stderr);
+
+	for (; opts->type != OPTION_END; opts++) {
+		size_t pos;
+		int pad;
+
+		if (opts->type == OPTION_GROUP) {
+			fputc('\n', stderr);
+			if (*opts->help)
+				fprintf(stderr, "%s\n", opts->help);
+			continue;
+		}
+		if (!full && (opts->flags & PARSE_OPT_HIDDEN))
+			continue;
+
+		pos = fprintf(stderr, "    ");
+		if (opts->short_name)
+			pos += fprintf(stderr, "-%c", opts->short_name);
+		else
+			pos += fprintf(stderr, "    ");
+
+		if (opts->long_name && opts->short_name)
+			pos += fprintf(stderr, ", ");
+		if (opts->long_name)
+			pos += fprintf(stderr, "--%s", opts->long_name);
+
+		switch (opts->type) {
+		case OPTION_ARGUMENT:
+			break;
+		case OPTION_LONG:
+		case OPTION_U64:
+		case OPTION_INTEGER:
+		case OPTION_UINTEGER:
+			if (opts->flags & PARSE_OPT_OPTARG)
+				if (opts->long_name)
+					pos += fprintf(stderr, "[=<n>]");
+				else
+					pos += fprintf(stderr, "[<n>]");
+			else
+				pos += fprintf(stderr, " <n>");
+			break;
+		case OPTION_CALLBACK:
+			if (opts->flags & PARSE_OPT_NOARG)
+				break;
+		/* FALLTHROUGH */
+		case OPTION_STRING:
+			if (opts->argh) {
+				if (opts->flags & PARSE_OPT_OPTARG)
+					if (opts->long_name)
+						pos += fprintf(stderr, "[=<%s>]", opts->argh);
+					else
+						pos += fprintf(stderr, "[<%s>]", opts->argh);
+				else
+					pos += fprintf(stderr, " <%s>", opts->argh);
+			} else {
+				if (opts->flags & PARSE_OPT_OPTARG)
+					if (opts->long_name)
+						pos += fprintf(stderr, "[=...]");
+					else
+						pos += fprintf(stderr, "[...]");
+				else
+					pos += fprintf(stderr, " ...");
+			}
+				break;
+		default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
+		case OPTION_END:
+		case OPTION_GROUP:
+		case OPTION_BIT:
+		case OPTION_BOOLEAN:
+		case OPTION_INCR:
+		case OPTION_SET_UINT:
+		case OPTION_SET_PTR:
+			break;
+		}
+		if (pos <= USAGE_OPTS_WIDTH)
+			pad = USAGE_OPTS_WIDTH - pos;
+		else {
+			fputc('\n', stderr);
+			pad = USAGE_OPTS_WIDTH;
+		}
+		fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
+	}
+	fputc('\n', stderr);
+
+	return PARSE_OPT_HELP;
+}
+
+void usage_with_options(const char * const *usagestr,
+		const struct option *opts)
+{
+	usage_with_options_internal(usagestr, opts, 0);
+	exit(129);
+}
+
+static void check_typos(const char *arg, const struct option *options)
+{
+	if (strlen(arg) < 3)
+		return;
+
+	if (!prefixcmp(arg, "no-")) {
+		pr_err("did you mean `--%s` (with two dashes ?)", arg);
+		exit(129);
+	}
+
+	for (; options->type != OPTION_END; options++) {
+		if (!options->long_name)
+			continue;
+		if (!prefixcmp(options->long_name, arg)) {
+			pr_err("did you mean `--%s` (with two dashes ?)", arg);
+			exit(129);
+		}
+	}
+}
+
+static int parse_options_usage(const char * const *usagestr,
+		const struct option *opts)
+{
+	return usage_with_options_internal(usagestr, opts, 0);
+}
+
+static int parse_short_opt(struct parse_opt_ctx_t *p,
+        const struct option *options)
+{
+	for (; options->type != OPTION_END; options++) {
+		if (options->short_name == *p->opt) {
+			p->opt = p->opt[1] ? p->opt + 1 : NULL;
+			return get_value(p, options, OPT_SHORT);
+		}
+	}
+	return -2;
+}
+
+static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
+		const struct option *options)
+{
+	const char *arg_end = strchr(arg, '=');
+	const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
+	int abbrev_flags = 0, ambiguous_flags = 0;
+
+	if (!arg_end)
+		arg_end = arg + strlen(arg);
+
+	for (; options->type != OPTION_END; options++) {
+		const char *rest;
+		int flags = 0;
+
+		if (!options->long_name)
+			continue;
+
+		rest = skip_prefix(arg, options->long_name);
+		if (options->type == OPTION_ARGUMENT) {
+			if (!rest)
+				continue;
+			if (*rest == '=')
+				return opterror(options, "takes no value",
+						flags);
+			if (*rest)
+				continue;
+			p->out[p->cpidx++] = arg - 2;
+			return 0;
+		}
+		if (!rest) {
+			/* abbreviated? */
+			if (!strncmp(options->long_name, arg, arg_end - arg)) {
+is_abbreviated:
+				if (abbrev_option) {
+					/*
+					 * If this is abbreviated, it is
+					 * ambiguous. So when there is no
+					 * exact match later, we need to
+					 * error out.
+					 */
+					ambiguous_option = abbrev_option;
+					ambiguous_flags = abbrev_flags;
+				}
+				if (!(flags & OPT_UNSET) && *arg_end)
+					p->opt = arg_end + 1;
+				abbrev_option = options;
+				abbrev_flags = flags;
+				continue;
+			}
+			/* negated and abbreviated very much? */
+			if (!prefixcmp("no-", arg)) {
+				flags |= OPT_UNSET;
+				goto is_abbreviated;
+			}
+			/* negated? */
+			if (strncmp(arg, "no-", 3))
+				continue;
+			flags |= OPT_UNSET;
+			rest = skip_prefix(arg + 3, options->long_name);
+			/* abbreviated and negated? */
+			if (!rest && !prefixcmp(options->long_name, arg + 3))
+				goto is_abbreviated;
+			if (!rest)
+				continue;
+		}
+		if (*rest) {
+			if (*rest != '=')
+				continue;
+			p->opt = rest + 1;
+		}
+		return get_value(p, options, flags);
+	}
+
+	if (ambiguous_option)
+		return pr_err("Ambiguous option: %s "
+				"(could be --%s%s or --%s%s)",
+				arg,
+				(ambiguous_flags & OPT_UNSET) ?  "no-" : "",
+				ambiguous_option->long_name,
+				(abbrev_flags & OPT_UNSET) ?  "no-" : "",
+				abbrev_option->long_name);
+	if (abbrev_option)
+		return get_value(p, abbrev_option, abbrev_flags);
+	return -2;
+}
+
+
+static void parse_options_start(struct parse_opt_ctx_t *ctx, int argc,
+		const char **argv, int flags)
+{
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->argc = argc;
+	ctx->argv = argv;
+	ctx->out  = argv;
+	ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
+	ctx->flags = flags;
+	if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
+			(flags & PARSE_OPT_STOP_AT_NON_OPTION))
+		die("STOP_AT_NON_OPTION and KEEP_UNKNOWN don't go together");
+}
+
+static int parse_options_end(struct parse_opt_ctx_t *ctx)
+{
+	memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
+	ctx->out[ctx->cpidx + ctx->argc] = NULL;
+	return ctx->cpidx + ctx->argc;
+}
+
+
+static int parse_options_step(struct parse_opt_ctx_t *ctx,
+		const struct option *options, const char * const usagestr[])
+{
+	int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
+
+	/* we must reset ->opt, unknown short option leave it dangling */
+	ctx->opt = NULL;
+
+	for (; ctx->argc; ctx->argc--, ctx->argv++) {
+		const char *arg = ctx->argv[0];
+
+		if (*arg != '-' || !arg[1]) {
+			if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
+				break;
+			ctx->out[ctx->cpidx++] = ctx->argv[0];
+			continue;
+		}
+
+		if (arg[1] != '-') {
+			ctx->opt = arg + 1;
+			if (internal_help && *ctx->opt == 'h')
+				return parse_options_usage(usagestr, options);
+			switch (parse_short_opt(ctx, options)) {
+			case -1:
+				return parse_options_usage(usagestr, options);
+			case -2:
+				goto unknown;
+			default:
+				break;
+			}
+			if (ctx->opt)
+				check_typos(arg + 1, options);
+			while (ctx->opt) {
+				if (internal_help && *ctx->opt == 'h')
+					return parse_options_usage(usagestr,
+							options);
+				switch (parse_short_opt(ctx, options)) {
+				case -1:
+					return parse_options_usage(usagestr,
+							options);
+				case -2:
+					/* fake a short option thing to hide
+					 * the fact that we may have
+					 * started to parse aggregated stuff
+					 *
+					 * This is leaky, too bad.
+					 */
+					ctx->argv[0] = strdup(ctx->opt - 1);
+					*(char *)ctx->argv[0] = '-';
+					goto unknown;
+				default:
+					break;
+				}
+			}
+			continue;
+		}
+
+		if (!arg[2]) { /* "--" */
+			if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
+				ctx->argc--;
+				ctx->argv++;
+			}
+			break;
+		}
+
+		if (internal_help && !strcmp(arg + 2, "help-all"))
+			return usage_with_options_internal(usagestr, options,
+					1);
+		if (internal_help && !strcmp(arg + 2, "help"))
+			return parse_options_usage(usagestr, options);
+		switch (parse_long_opt(ctx, arg + 2, options)) {
+		case -1:
+			return parse_options_usage(usagestr, options);
+		case -2:
+			goto unknown;
+		default:
+			break;
+		}
+		continue;
+unknown:
+		if (!(ctx->flags & PARSE_OPT_KEEP_UNKNOWN))
+			return PARSE_OPT_UNKNOWN;
+		ctx->out[ctx->cpidx++] = ctx->argv[0];
+		ctx->opt = NULL;
+	}
+	return PARSE_OPT_DONE;
+}
+
+int parse_options(int argc, const char **argv, const struct option *options,
+		const char * const usagestr[], int flags)
+{
+	struct parse_opt_ctx_t ctx;
+
+	parse_options_start(&ctx, argc, argv, flags);
+	switch (parse_options_step(&ctx, options, usagestr)) {
+	case PARSE_OPT_HELP:
+		exit(129);
+	case PARSE_OPT_DONE:
+		break;
+	default: /* PARSE_OPT_UNKNOWN */
+		if (ctx.argv[0][1] == '-') {
+			pr_err("unknown option `%s'", ctx.argv[0] + 2);
+		} else {
+			pr_err("unknown switch `%c'", *ctx.opt);
+		}
+		usage_with_options(usagestr, options);
+	}
+
+	return parse_options_end(&ctx);
+}
diff --git a/tools/kvm/util/rbtree-interval.c b/tools/kvm/util/rbtree-interval.c
new file mode 100644
index 0000000..d02fbf0
--- /dev/null
+++ b/tools/kvm/util/rbtree-interval.c
@@ -0,0 +1,90 @@
+#include <kvm/rbtree-interval.h>
+#include <stddef.h>
+
+#define rb_int(n) rb_entry(n, struct rb_int_node, node)
+
+struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point)
+{
+	struct rb_node *node = root->rb_node;
+	struct rb_node *lowest = NULL;
+
+	while (node) {
+		struct rb_int_node *cur = rb_int(node);
+
+		if (node->rb_left && (rb_int(node->rb_left)->max_high > point)) {
+			node = node->rb_left;
+		} else if (cur->low <= point && cur->high > point) {
+			lowest = node;
+			break;
+		} else if (point > cur->low) {
+			node = node->rb_right;
+		} else {
+			break;
+		}
+	}
+
+	if (lowest == NULL)
+		return NULL;
+
+	return rb_int(lowest);
+}
+
+struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high)
+{
+	struct rb_int_node *range;
+
+	range = rb_int_search_single(root, low);
+	if (range == NULL)
+		return NULL;
+
+	/* We simply verify that 'high' is smaller than the end of the range where 'low' is located */
+	if (range->high < high)
+		return NULL;
+
+	return range;
+}
+
+static void update_node_max_high(struct rb_node *node, void *arg)
+{
+	struct rb_int_node *i_node = rb_int(node);
+
+	i_node->max_high = i_node->high;
+
+	if (node->rb_left)
+		i_node->max_high = max(i_node->max_high, rb_int(node->rb_left)->max_high);
+	if (node->rb_right)
+		i_node->max_high = max(i_node->max_high, rb_int(node->rb_right)->max_high);
+}
+
+int rb_int_insert(struct rb_root *root, struct rb_int_node *i_node)
+{
+	struct rb_node **node	= &(root->rb_node), *parent = NULL;
+
+	while (*node) {
+		int result	= i_node->low - rb_int(*node)->low;
+
+		parent = *node;
+		if (result < 0)
+			node	= &((*node)->rb_left);
+		else if (result > 0)
+			node	= &((*node)->rb_right);
+		else
+			return 0;
+	}
+
+	rb_link_node(&i_node->node, parent, node);
+	rb_insert_color(&i_node->node, root);
+
+	rb_augment_insert(&i_node->node, update_node_max_high, NULL);
+	return 1;
+}
+
+void rb_int_erase(struct rb_root *root, struct rb_int_node *node)
+{
+	struct rb_node *deepest;
+
+	deepest = rb_augment_erase_begin(&node->node);
+	rb_erase(&node->node, root);
+	rb_augment_erase_end(deepest, update_node_max_high, NULL);
+
+}
diff --git a/tools/kvm/util/read-write.c b/tools/kvm/util/read-write.c
new file mode 100644
index 0000000..55473ba
--- /dev/null
+++ b/tools/kvm/util/read-write.c
@@ -0,0 +1,344 @@
+#include "kvm/read-write.h"
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+/* Same as read(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xread(int fd, void *buf, size_t count)
+{
+	ssize_t nr;
+
+restart:
+	nr = read(fd, buf, count);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+/* Same as write(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xwrite(int fd, const void *buf, size_t count)
+{
+	ssize_t nr;
+
+restart:
+	nr = write(fd, buf, count);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+ssize_t read_in_full(int fd, void *buf, size_t count)
+{
+	ssize_t total = 0;
+	char *p = buf;
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xread(fd, p, count);
+		if (nr <= 0) {
+			if (total > 0)
+				return total;
+
+			return -1;
+		}
+
+		count -= nr;
+		total += nr;
+		p += nr;
+	}
+
+	return total;
+}
+
+ssize_t write_in_full(int fd, const void *buf, size_t count)
+{
+	const char *p = buf;
+	ssize_t total = 0;
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xwrite(fd, p, count);
+		if (nr < 0)
+			return -1;
+		if (nr == 0) {
+			errno = ENOSPC;
+			return -1;
+		}
+		count -= nr;
+		total += nr;
+		p += nr;
+	}
+
+	return total;
+}
+
+/* Same as pread(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpread(int fd, void *buf, size_t count, off_t offset)
+{
+	ssize_t nr;
+
+restart:
+	nr = pread(fd, buf, count, offset);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+/* Same as pwrite(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+	ssize_t nr;
+
+restart:
+	nr = pwrite(fd, buf, count, offset);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
+{
+	ssize_t total = 0;
+	char *p = buf;
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xpread(fd, p, count, offset);
+		if (nr <= 0) {
+			if (total > 0)
+				return total;
+
+			return -1;
+		}
+
+		count -= nr;
+		total += nr;
+		p += nr;
+		offset += nr;
+	}
+
+	return total;
+}
+
+ssize_t pwrite_in_full(int fd, const void *buf, size_t count, off_t offset)
+{
+	const char *p = buf;
+	ssize_t total = 0;
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xpwrite(fd, p, count, offset);
+		if (nr < 0)
+			return -1;
+		if (nr == 0) {
+			errno = ENOSPC;
+			return -1;
+		}
+		count -= nr;
+		total += nr;
+		p += nr;
+		offset += nr;
+	}
+
+	return total;
+}
+
+/* Same as readv(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xreadv(int fd, const struct iovec *iov, int iovcnt)
+{
+	ssize_t nr;
+
+restart:
+	nr = readv(fd, iov, iovcnt);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+/* Same as writev(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xwritev(int fd, const struct iovec *iov, int iovcnt)
+{
+	ssize_t nr;
+
+restart:
+	nr = writev(fd, iov, iovcnt);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+static inline ssize_t get_iov_size(const struct iovec *iov, int iovcnt)
+{
+	size_t size = 0;
+	while (iovcnt--)
+		size += (iov++)->iov_len;
+
+	return size;
+}
+
+static inline void shift_iovec(const struct iovec **iov, int *iovcnt,
+				size_t nr, ssize_t *total, size_t *count, off_t *offset)
+{
+	while (nr >= (*iov)->iov_len) {
+		nr -= (*iov)->iov_len;
+		*total += (*iov)->iov_len;
+		*count -= (*iov)->iov_len;
+		if (offset)
+			*offset += (*iov)->iov_len;
+		(*iovcnt)--;
+		(*iov)++;
+	}
+}
+
+ssize_t readv_in_full(int fd, const struct iovec *iov, int iovcnt)
+{
+	ssize_t total = 0;
+	size_t count = get_iov_size(iov, iovcnt);
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xreadv(fd, iov, iovcnt);
+		if (nr <= 0) {
+			if (total > 0)
+				return total;
+
+			return -1;
+		}
+
+		shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
+	}
+
+	return total;
+}
+
+ssize_t writev_in_full(int fd, const struct iovec *iov, int iovcnt)
+{
+	ssize_t total = 0;
+	size_t count = get_iov_size(iov, iovcnt);
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xwritev(fd, iov, iovcnt);
+		if (nr < 0)
+			return -1;
+		if (nr == 0) {
+			errno = ENOSPC;
+			return -1;
+		}
+
+		shift_iovec(&iov, &iovcnt, nr, &total, &count, NULL);
+	}
+
+	return total;
+}
+
+/* Same as preadv(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpreadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+	ssize_t nr;
+
+restart:
+	nr = preadv(fd, iov, iovcnt, offset);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+/* Same as pwritev(2) except that this function never returns EAGAIN or EINTR. */
+ssize_t xpwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+	ssize_t nr;
+
+restart:
+	nr = pwritev(fd, iov, iovcnt, offset);
+	if ((nr < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+		goto restart;
+
+	return nr;
+}
+
+ssize_t preadv_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+	ssize_t total = 0;
+	size_t count = get_iov_size(iov, iovcnt);
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xpreadv(fd, iov, iovcnt, offset);
+		if (nr <= 0) {
+			if (total > 0)
+				return total;
+
+			return -1;
+		}
+
+		shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
+	}
+
+	return total;
+}
+
+ssize_t pwritev_in_full(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+	ssize_t total = 0;
+	size_t count = get_iov_size(iov, iovcnt);
+
+	while (count > 0) {
+		ssize_t nr;
+
+		nr = xpwritev(fd, iov, iovcnt, offset);
+		if (nr < 0)
+			return -1;
+		if (nr == 0) {
+			errno = ENOSPC;
+			return -1;
+		}
+
+		shift_iovec(&iov, &iovcnt, nr, &total, &count, &offset);
+	}
+
+	return total;
+}
+
+#ifdef CONFIG_HAS_AIO
+int aio_pwritev(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+		off_t offset, int ev, void *param)
+{
+	struct iocb *ios[1] = { iocb };
+
+	io_prep_pwritev(iocb, fd, iov, iovcnt, offset);
+	io_set_eventfd(iocb, ev);
+	iocb->data = param;
+
+	return io_submit(ctx, 1, ios);
+}
+
+int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
+		off_t offset, int ev, void *param)
+{
+	struct iocb *ios[1] = { iocb };
+
+	io_prep_preadv(iocb, fd, iov, iovcnt, offset);
+	io_set_eventfd(iocb, ev);
+	iocb->data = param;
+
+	return io_submit(ctx, 1, ios);
+}
+#endif
\ No newline at end of file
diff --git a/tools/kvm/util/set_private_br.sh b/tools/kvm/util/set_private_br.sh
new file mode 100755
index 0000000..49867dd
--- /dev/null
+++ b/tools/kvm/util/set_private_br.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Author: Amos Kong <kongjianjun@gmail.com>
+# Date: Apr 14, 2011
+# Description: this script is used to create/delete a private bridge,
+# launch a dhcp server on the bridge by dnsmasq.
+#
+# @ ./set_private_br.sh $bridge_name $subnet_prefix
+# @ ./set_private_br.sh vbr0 192.168.33
+
+brname='vbr0'
+subnet='192.168.33'
+
+add_br()
+{
+    echo "add new private bridge: $brname"
+    /usr/sbin/brctl addbr $brname
+    echo 1 > /proc/sys/net/ipv6/conf/$brname/disable_ipv6
+    echo 1 > /proc/sys/net/ipv4/ip_forward
+    /usr/sbin/brctl stp $brname on
+    /usr/sbin/brctl setfd $brname 0
+    ifconfig $brname $subnet.1
+    ifconfig $brname up
+    # Add forward rule, then guest can access public network
+    iptables -t nat -A POSTROUTING -s $subnet.254/24 ! -d $subnet.254/24 -j MASQUERADE
+    /etc/init.d/dnsmasq stop
+    /etc/init.d/tftpd-hpa stop 2>/dev/null
+    dnsmasq --strict-order --bind-interfaces --listen-address $subnet.1 --dhcp-range $subnet.1,$subnet.254 $tftp_cmd
+}
+
+del_br()
+{
+    echo "cleanup bridge setup"
+    kill -9 `pgrep dnsmasq|tail -1`
+    ifconfig $brname down
+    /usr/sbin/brctl delbr $brname
+    iptables -t nat -D POSTROUTING -s $subnet.254/24 ! -d $subnet.254/24 -j MASQUERADE
+}
+
+
+if [ $# = 0 ]; then
+    del_br 2>/dev/null
+    exit
+fi
+if [ $# > 1 ]; then
+    brname="$1"
+fi
+if [ $# = 2 ]; then
+    subnet="$2"
+fi
+add_br
diff --git a/tools/kvm/util/strbuf.c b/tools/kvm/util/strbuf.c
new file mode 100644
index 0000000..6632a14
--- /dev/null
+++ b/tools/kvm/util/strbuf.c
@@ -0,0 +1,39 @@
+
+/* user defined headers */
+#include <kvm/util.h>
+#include <kvm/strbuf.h>
+
+int prefixcmp(const char *str, const char *prefix)
+{
+	for (; ; str++, prefix++) {
+		if (!*prefix)
+			return 0;
+		else if (*str != *prefix)
+			return (unsigned char)*prefix - (unsigned char)*str;
+	}
+}
+
+/**
+ * strlcat - Append a length-limited, %NUL-terminated string to another
+ * @dest: The string to be appended to
+ * @src: The string to append to it
+ * @count: The size of the destination buffer.
+ */
+size_t strlcat(char *dest, const char *src, size_t count)
+{
+	size_t dsize = strlen(dest);
+	size_t len = strlen(src);
+	size_t res = dsize + len;
+
+	DIE_IF(dsize >= count);
+
+	dest += dsize;
+	count -= dsize;
+	if (len >= count)
+		len = count - 1;
+
+	memcpy(dest, src, len);
+	dest[len] = 0;
+
+	return res;
+}
diff --git a/tools/kvm/util/threadpool.c b/tools/kvm/util/threadpool.c
new file mode 100644
index 0000000..bafbcd7
--- /dev/null
+++ b/tools/kvm/util/threadpool.c
@@ -0,0 +1,145 @@
+#include "kvm/threadpool.h"
+#include "kvm/mutex.h"
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <pthread.h>
+#include <stdbool.h>
+
+static pthread_mutex_t	job_mutex	= PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t	thread_mutex	= PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t	job_cond	= PTHREAD_COND_INITIALIZER;
+
+static LIST_HEAD(head);
+
+static pthread_t	*threads;
+static long		threadcount;
+
+static struct thread_pool__job *thread_pool__job_pop_locked(void)
+{
+	struct thread_pool__job *job;
+
+	if (list_empty(&head))
+		return NULL;
+
+	job = list_first_entry(&head, struct thread_pool__job, queue);
+	list_del(&job->queue);
+
+	return job;
+}
+
+static void thread_pool__job_push_locked(struct thread_pool__job *job)
+{
+	list_add_tail(&job->queue, &head);
+}
+
+static struct thread_pool__job *thread_pool__job_pop(void)
+{
+	struct thread_pool__job *job;
+
+	mutex_lock(&job_mutex);
+	job = thread_pool__job_pop_locked();
+	mutex_unlock(&job_mutex);
+	return job;
+}
+
+static void thread_pool__job_push(struct thread_pool__job *job)
+{
+	mutex_lock(&job_mutex);
+	thread_pool__job_push_locked(job);
+	mutex_unlock(&job_mutex);
+}
+
+static void thread_pool__handle_job(struct thread_pool__job *job)
+{
+	while (job) {
+		job->callback(job->kvm, job->data);
+
+		mutex_lock(&job->mutex);
+
+		if (--job->signalcount > 0)
+			/* If the job was signaled again while we were working */
+			thread_pool__job_push(job);
+
+		mutex_unlock(&job->mutex);
+
+		job = thread_pool__job_pop();
+	}
+}
+
+static void thread_pool__threadfunc_cleanup(void *param)
+{
+	mutex_unlock(&job_mutex);
+}
+
+static void *thread_pool__threadfunc(void *param)
+{
+	pthread_cleanup_push(thread_pool__threadfunc_cleanup, NULL);
+
+	for (;;) {
+		struct thread_pool__job *curjob;
+
+		mutex_lock(&job_mutex);
+		while ((curjob = thread_pool__job_pop_locked()) == NULL)
+			pthread_cond_wait(&job_cond, &job_mutex);
+		mutex_unlock(&job_mutex);
+
+		thread_pool__handle_job(curjob);
+	}
+
+	pthread_cleanup_pop(0);
+
+	return NULL;
+}
+
+static int thread_pool__addthread(void)
+{
+	int res;
+	void *newthreads;
+
+	mutex_lock(&thread_mutex);
+	newthreads = realloc(threads, (threadcount + 1) * sizeof(pthread_t));
+	if (newthreads == NULL) {
+		mutex_unlock(&thread_mutex);
+		return -1;
+	}
+
+	threads = newthreads;
+
+	res = pthread_create(threads + threadcount, NULL,
+			     thread_pool__threadfunc, NULL);
+
+	if (res == 0)
+		threadcount++;
+	mutex_unlock(&thread_mutex);
+
+	return res;
+}
+
+int thread_pool__init(unsigned long thread_count)
+{
+	unsigned long i;
+
+	for (i = 0; i < thread_count; i++)
+		if (thread_pool__addthread() < 0)
+			return i;
+
+	return i;
+}
+
+void thread_pool__do_job(struct thread_pool__job *job)
+{
+	struct thread_pool__job *jobinfo = job;
+
+	if (jobinfo == NULL || jobinfo->callback == NULL)
+		return;
+
+	mutex_lock(&jobinfo->mutex);
+	if (jobinfo->signalcount++ == 0)
+		thread_pool__job_push(job);
+	mutex_unlock(&jobinfo->mutex);
+
+	mutex_lock(&job_mutex);
+	pthread_cond_signal(&job_cond);
+	mutex_unlock(&job_mutex);
+}
diff --git a/tools/kvm/util/util.c b/tools/kvm/util/util.c
new file mode 100644
index 0000000..e7feebc
--- /dev/null
+++ b/tools/kvm/util/util.c
@@ -0,0 +1,115 @@
+/*
+ * Taken from perf which in turn take it from GIT
+ */
+
+#include "kvm/util.h"
+
+#include <linux/magic.h>	/* For HUGETLBFS_MAGIC */
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+
+static void report(const char *prefix, const char *err, va_list params)
+{
+	char msg[1024];
+	vsnprintf(msg, sizeof(msg), err, params);
+	fprintf(stderr, " %s%s\n", prefix, msg);
+}
+
+static NORETURN void die_builtin(const char *err, va_list params)
+{
+	report(" Fatal: ", err, params);
+	exit(128);
+}
+
+static void error_builtin(const char *err, va_list params)
+{
+	report(" Error: ", err, params);
+}
+
+static void warn_builtin(const char *warn, va_list params)
+{
+	report(" Warning: ", warn, params);
+}
+
+static void info_builtin(const char *info, va_list params)
+{
+	report(" Info: ", info, params);
+}
+
+void die(const char *err, ...)
+{
+	va_list params;
+
+	va_start(params, err);
+	die_builtin(err, params);
+	va_end(params);
+}
+
+int pr_err(const char *err, ...)
+{
+	va_list params;
+
+	va_start(params, err);
+	error_builtin(err, params);
+	va_end(params);
+	return -1;
+}
+
+void pr_warning(const char *warn, ...)
+{
+	va_list params;
+
+	va_start(params, warn);
+	warn_builtin(warn, params);
+	va_end(params);
+}
+
+void pr_info(const char *info, ...)
+{
+	va_list params;
+
+	va_start(params, info);
+	info_builtin(info, params);
+	va_end(params);
+}
+
+void die_perror(const char *s)
+{
+	perror(s);
+	exit(1);
+}
+
+void *mmap_hugetlbfs(const char *htlbfs_path, u64 size)
+{
+	char mpath[PATH_MAX];
+	int fd;
+	struct statfs sfs;
+	void *addr;
+	unsigned long blk_size;
+
+	if (statfs(htlbfs_path, &sfs) < 0)
+		die("Can't stat %s\n", htlbfs_path);
+
+	if ((unsigned int)sfs.f_type != HUGETLBFS_MAGIC)
+		die("%s is not hugetlbfs!\n", htlbfs_path);
+
+	blk_size = (unsigned long)sfs.f_bsize;
+	if (sfs.f_bsize == 0 || blk_size > size) {
+		die("Can't use hugetlbfs pagesize %ld for mem size %lld\n",
+		    blk_size, size);
+	}
+
+	snprintf(mpath, PATH_MAX, "%s/kvmtoolXXXXXX", htlbfs_path);
+	fd = mkstemp(mpath);
+	if (fd < 0)
+		die("Can't open %s for hugetlbfs map\n", mpath);
+	unlink(mpath);
+	if (ftruncate(fd, size) < 0)
+		die("Can't ftruncate for mem mapping size %lld\n",
+		    size);
+	addr = mmap(NULL, size, PROT_RW, MAP_PRIVATE, fd, 0);
+	close(fd);
+
+	return addr;
+}
diff --git a/tools/kvm/virtio/9p-pdu.c b/tools/kvm/virtio/9p-pdu.c
new file mode 100644
index 0000000..b9ce8ce
--- /dev/null
+++ b/tools/kvm/virtio/9p-pdu.c
@@ -0,0 +1,287 @@
+#include "kvm/util.h"
+#include "kvm/virtio-9p.h"
+
+#include <endian.h>
+#include <stdint.h>
+
+#include <linux/compiler.h>
+#include <net/9p/9p.h>
+
+static void virtio_p9_pdu_read(struct p9_pdu *pdu, void *data, size_t size)
+{
+	size_t len;
+	int i, copied = 0;
+	u16 iov_cnt = pdu->out_iov_cnt;
+	size_t offset = pdu->read_offset;
+	struct iovec *iov = pdu->out_iov;
+
+	for (i = 0; i < iov_cnt && size; i++) {
+		if (offset >= iov[i].iov_len) {
+			offset -= iov[i].iov_len;
+			continue;
+		} else {
+			len = MIN(iov[i].iov_len - offset, size);
+			memcpy(data, iov[i].iov_base + offset, len);
+			size -= len;
+			data += len;
+			offset = 0;
+			copied += len;
+		}
+	}
+	pdu->read_offset += copied;
+}
+
+static void virtio_p9_pdu_write(struct p9_pdu *pdu,
+				const void *data, size_t size)
+{
+	size_t len;
+	int i, copied = 0;
+	u16 iov_cnt = pdu->in_iov_cnt;
+	size_t offset = pdu->write_offset;
+	struct iovec *iov = pdu->in_iov;
+
+	for (i = 0; i < iov_cnt && size; i++) {
+		if (offset >= iov[i].iov_len) {
+			offset -= iov[i].iov_len;
+			continue;
+		} else {
+			len = MIN(iov[i].iov_len - offset, size);
+			memcpy(iov[i].iov_base + offset, data, len);
+			size -= len;
+			data += len;
+			offset = 0;
+			copied += len;
+		}
+	}
+	pdu->write_offset += copied;
+}
+
+static void virtio_p9_wstat_free(struct p9_wstat *stbuf)
+{
+	free(stbuf->name);
+	free(stbuf->uid);
+	free(stbuf->gid);
+	free(stbuf->muid);
+}
+
+static int virtio_p9_decode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+	int retval = 0;
+	const char *ptr;
+
+	for (ptr = fmt; *ptr; ptr++) {
+		switch (*ptr) {
+		case 'b':
+		{
+			int8_t *val = va_arg(ap, int8_t *);
+			virtio_p9_pdu_read(pdu, val, sizeof(*val));
+		}
+		break;
+		case 'w':
+		{
+			int16_t le_val;
+			int16_t *val = va_arg(ap, int16_t *);
+			virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+			*val = le16toh(le_val);
+		}
+		break;
+		case 'd':
+		{
+			int32_t le_val;
+			int32_t *val = va_arg(ap, int32_t *);
+			virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+			*val = le32toh(le_val);
+		}
+		break;
+		case 'q':
+		{
+			int64_t le_val;
+			int64_t *val = va_arg(ap, int64_t *);
+			virtio_p9_pdu_read(pdu, &le_val, sizeof(le_val));
+			*val = le64toh(le_val);
+		}
+		break;
+		case 's':
+		{
+			int16_t len;
+			char **str = va_arg(ap, char **);
+
+			virtio_p9_pdu_readf(pdu, "w", &len);
+			*str = malloc(len + 1);
+			if (*str == NULL) {
+				retval = ENOMEM;
+				break;
+			}
+			virtio_p9_pdu_read(pdu, *str, len);
+			(*str)[len] = 0;
+		}
+		break;
+		case 'Q':
+		{
+			struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+			retval = virtio_p9_pdu_readf(pdu, "bdq",
+						     &qid->type, &qid->version,
+						     &qid->path);
+		}
+		break;
+		case 'S':
+		{
+			struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+			memset(stbuf, 0, sizeof(struct p9_wstat));
+			stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = -1;
+			retval = virtio_p9_pdu_readf(pdu, "wwdQdddqssss",
+						&stbuf->size, &stbuf->type,
+						&stbuf->dev, &stbuf->qid,
+						&stbuf->mode, &stbuf->atime,
+						&stbuf->mtime, &stbuf->length,
+						&stbuf->name, &stbuf->uid,
+						&stbuf->gid, &stbuf->muid);
+			if (retval)
+				virtio_p9_wstat_free(stbuf);
+		}
+		break;
+		case 'I':
+		{
+			struct p9_iattr_dotl *p9attr = va_arg(ap,
+						       struct p9_iattr_dotl *);
+
+			retval = virtio_p9_pdu_readf(pdu, "ddddqqqqq",
+						     &p9attr->valid,
+						     &p9attr->mode,
+						     &p9attr->uid,
+						     &p9attr->gid,
+						     &p9attr->size,
+						     &p9attr->atime_sec,
+						     &p9attr->atime_nsec,
+						     &p9attr->mtime_sec,
+						     &p9attr->mtime_nsec);
+		}
+		break;
+		default:
+			retval = EINVAL;
+			break;
+		}
+	}
+	return retval;
+}
+
+static int virtio_p9_pdu_encode(struct p9_pdu *pdu, const char *fmt, va_list ap)
+{
+	int retval = 0;
+	const char *ptr;
+
+	for (ptr = fmt; *ptr; ptr++) {
+		switch (*ptr) {
+		case 'b':
+		{
+			int8_t val = va_arg(ap, int);
+			virtio_p9_pdu_write(pdu, &val, sizeof(val));
+		}
+		break;
+		case 'w':
+		{
+			int16_t val = htole16(va_arg(ap, int));
+			virtio_p9_pdu_write(pdu, &val, sizeof(val));
+		}
+		break;
+		case 'd':
+		{
+			int32_t val = htole32(va_arg(ap, int32_t));
+			virtio_p9_pdu_write(pdu, &val, sizeof(val));
+		}
+		break;
+		case 'q':
+		{
+			int64_t val = htole64(va_arg(ap, int64_t));
+			virtio_p9_pdu_write(pdu, &val, sizeof(val));
+		}
+		break;
+		case 's':
+		{
+			uint16_t len = 0;
+			const char *s = va_arg(ap, char *);
+			if (s)
+				len = MIN(strlen(s), USHRT_MAX);
+			virtio_p9_pdu_writef(pdu, "w", len);
+			virtio_p9_pdu_write(pdu, s, len);
+		}
+		break;
+		case 'Q':
+		{
+			struct p9_qid *qid = va_arg(ap, struct p9_qid *);
+			retval = virtio_p9_pdu_writef(pdu, "bdq",
+						      qid->type, qid->version,
+						      qid->path);
+		}
+		break;
+		case 'S':
+		{
+			struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *);
+			retval = virtio_p9_pdu_writef(pdu, "wwdQdddqssss",
+						stbuf->size, stbuf->type,
+						stbuf->dev, &stbuf->qid,
+						stbuf->mode, stbuf->atime,
+						stbuf->mtime, stbuf->length,
+						stbuf->name, stbuf->uid,
+						stbuf->gid, stbuf->muid);
+		}
+		break;
+		case 'A':
+		{
+			struct p9_stat_dotl *stbuf = va_arg(ap,
+						      struct p9_stat_dotl *);
+			retval  = virtio_p9_pdu_writef(pdu,
+						       "qQdddqqqqqqqqqqqqqqq",
+						       stbuf->st_result_mask,
+						       &stbuf->qid,
+						       stbuf->st_mode,
+						       stbuf->st_uid,
+						       stbuf->st_gid,
+						       stbuf->st_nlink,
+						       stbuf->st_rdev,
+						       stbuf->st_size,
+						       stbuf->st_blksize,
+						       stbuf->st_blocks,
+						       stbuf->st_atime_sec,
+						       stbuf->st_atime_nsec,
+						       stbuf->st_mtime_sec,
+						       stbuf->st_mtime_nsec,
+						       stbuf->st_ctime_sec,
+						       stbuf->st_ctime_nsec,
+						       stbuf->st_btime_sec,
+						       stbuf->st_btime_nsec,
+						       stbuf->st_gen,
+						       stbuf->st_data_version);
+		}
+		break;
+		default:
+			retval = EINVAL;
+			break;
+		}
+	}
+	return retval;
+}
+
+int virtio_p9_pdu_readf(struct p9_pdu *pdu, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = virtio_p9_decode(pdu, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+int virtio_p9_pdu_writef(struct p9_pdu *pdu, const char *fmt, ...)
+{
+	int ret;
+	va_list ap;
+
+	va_start(ap, fmt);
+	ret = virtio_p9_pdu_encode(pdu, fmt, ap);
+	va_end(ap);
+
+	return ret;
+}
diff --git a/tools/kvm/virtio/9p.c b/tools/kvm/virtio/9p.c
new file mode 100644
index 0000000..28f5ed7
--- /dev/null
+++ b/tools/kvm/virtio/9p.c
@@ -0,0 +1,1326 @@
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/virtio-9p.h"
+#include "kvm/guest_compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/vfs.h>
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_9p.h>
+#include <net/9p/9p.h>
+
+static LIST_HEAD(devs);
+static int compat_id = -1;
+
+/* Warning: Immediately use value returned from this function */
+static const char *rel_to_abs(struct p9_dev *p9dev,
+			      const char *path, char *abs_path)
+{
+	sprintf(abs_path, "%s/%s", p9dev->root_dir, path);
+
+	return abs_path;
+}
+
+static void stat2qid(struct stat *st, struct p9_qid *qid)
+{
+	*qid = (struct p9_qid) {
+		.path		= st->st_ino,
+		.version	= st->st_mtime,
+	};
+
+	if (S_ISDIR(st->st_mode))
+		qid->type	|= P9_QTDIR;
+}
+
+static void close_fid(struct p9_dev *p9dev, u32 fid)
+{
+	if (p9dev->fids[fid].fd > 0) {
+		close(p9dev->fids[fid].fd);
+		p9dev->fids[fid].fd = -1;
+	}
+	if (p9dev->fids[fid].dir) {
+		closedir(p9dev->fids[fid].dir);
+		p9dev->fids[fid].dir = NULL;
+	}
+	p9dev->fids[fid].fid = P9_NOFID;
+}
+
+static void virtio_p9_set_reply_header(struct p9_pdu *pdu, u32 size)
+{
+	u8 cmd;
+	u16 tag;
+
+	pdu->read_offset = sizeof(u32);
+	virtio_p9_pdu_readf(pdu, "bw", &cmd, &tag);
+	pdu->write_offset = 0;
+	/* cmd + 1 is the reply message */
+	virtio_p9_pdu_writef(pdu, "dbw", size, cmd + 1, tag);
+}
+
+static u16 virtio_p9_update_iov_cnt(struct iovec iov[], u32 count, int iov_cnt)
+{
+	int i;
+	u32 total = 0;
+	for (i = 0; (i < iov_cnt) && (total < count); i++) {
+		if (total + iov[i].iov_len > count) {
+			/* we don't need this iov fully */
+			iov[i].iov_len -= ((total + iov[i].iov_len) - count);
+			i++;
+			break;
+		}
+		total += iov[i].iov_len;
+	}
+	return i;
+}
+
+static void virtio_p9_error_reply(struct p9_dev *p9dev,
+				  struct p9_pdu *pdu, int err, u32 *outlen)
+{
+	u16 tag;
+
+	pdu->write_offset = VIRTIO_P9_HDR_LEN;
+	virtio_p9_pdu_writef(pdu, "d", err);
+	*outlen = pdu->write_offset;
+
+	/* read the tag from input */
+	pdu->read_offset = sizeof(u32) + sizeof(u8);
+	virtio_p9_pdu_readf(pdu, "w", &tag);
+
+	/* Update the header */
+	pdu->write_offset = 0;
+	virtio_p9_pdu_writef(pdu, "dbw", *outlen, P9_RLERROR, tag);
+}
+
+static void virtio_p9_version(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 msize;
+	char *version;
+	virtio_p9_pdu_readf(pdu, "ds", &msize, &version);
+	/*
+	 * reply with the same msize the client sent us
+	 * Error out if the request is not for 9P2000.L
+	 */
+	if (!strcmp(version, VIRTIO_P9_VERSION_DOTL))
+		virtio_p9_pdu_writef(pdu, "ds", msize, version);
+	else
+		virtio_p9_pdu_writef(pdu, "ds", msize, "unknown");
+
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	free(version);
+	return;
+}
+
+static void virtio_p9_clunk(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 fid;
+
+	virtio_p9_pdu_readf(pdu, "d", &fid);
+	close_fid(p9dev, fid);
+
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+}
+
+/*
+ * FIXME!! Need to map to protocol independent value. Upstream
+ * 9p also have the same BUG
+ */
+static int virtio_p9_openflags(int flags)
+{
+	flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT | O_DIRECT);
+	flags |= O_NOFOLLOW;
+	return flags;
+}
+
+static void virtio_p9_open(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 fid, flags;
+	struct stat st;
+	struct p9_qid qid;
+	struct p9_fid *new_fid;
+
+
+	virtio_p9_pdu_readf(pdu, "dd", &fid, &flags);
+	new_fid = &p9dev->fids[fid];
+
+	if (lstat(new_fid->abs_path, &st) < 0)
+		goto err_out;
+
+	stat2qid(&st, &qid);
+
+	if (new_fid->is_dir) {
+		new_fid->dir = opendir(new_fid->abs_path);
+		if (!new_fid->dir)
+			goto err_out;
+	} else {
+		new_fid->fd  = open(new_fid->abs_path,
+				    virtio_p9_openflags(flags));
+		if (new_fid->fd < 0)
+			goto err_out;
+	}
+	/* FIXME!! need ot send proper iounit  */
+	virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_create(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
+{
+	int fd, ret;
+	char *name;
+	struct stat st;
+	struct p9_qid qid;
+	struct p9_fid *dfid;
+	char full_path[PATH_MAX];
+	u32 dfid_val, flags, mode, gid;
+
+	virtio_p9_pdu_readf(pdu, "dsddd", &dfid_val,
+			    &name, &flags, &mode, &gid);
+	dfid = &p9dev->fids[dfid_val];
+
+	flags = virtio_p9_openflags(flags);
+
+	sprintf(full_path, "%s/%s", dfid->abs_path, name);
+	fd = open(full_path, flags | O_CREAT, mode);
+	if (fd < 0)
+		goto err_out;
+	close_fid(p9dev, dfid_val);
+	dfid->fd = fd;
+
+	if (lstat(full_path, &st) < 0)
+		goto err_out;
+
+	ret = chmod(full_path, mode & 0777);
+	if (ret < 0)
+		goto err_out;
+
+	ret = lchown(full_path, dfid->uid, gid);
+	if (ret < 0)
+		goto err_out;
+
+	sprintf(dfid->path, "%s/%s", dfid->path, name);
+	stat2qid(&st, &qid);
+	virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	free(name);
+	return;
+err_out:
+	free(name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_mkdir(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	char *name;
+	struct stat st;
+	struct p9_qid qid;
+	struct p9_fid *dfid;
+	char full_path[PATH_MAX];
+	u32 dfid_val, mode, gid;
+
+	virtio_p9_pdu_readf(pdu, "dsdd", &dfid_val,
+			    &name, &mode, &gid);
+	dfid = &p9dev->fids[dfid_val];
+
+	sprintf(full_path, "%s/%s", dfid->abs_path, name);
+	ret = mkdir(full_path, mode);
+	if (ret < 0)
+		goto err_out;
+
+	if (lstat(full_path, &st) < 0)
+		goto err_out;
+
+	ret = chmod(full_path, mode & 0777);
+	if (ret < 0)
+		goto err_out;
+
+	ret = lchown(full_path, dfid->uid, gid);
+	if (ret < 0)
+		goto err_out;
+
+	stat2qid(&st, &qid);
+	virtio_p9_pdu_writef(pdu, "Qd", &qid, 0);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	free(name);
+	return;
+err_out:
+	free(name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_walk(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
+{
+	u8 i;
+	u16 nwqid;
+	u16 nwname;
+	struct p9_qid wqid;
+	struct p9_fid *new_fid;
+	u32 fid_val, newfid_val;
+
+
+	virtio_p9_pdu_readf(pdu, "ddw", &fid_val, &newfid_val, &nwname);
+	new_fid	= &p9dev->fids[newfid_val];
+
+	nwqid = 0;
+	if (nwname) {
+		struct p9_fid *fid = &p9dev->fids[fid_val];
+
+		strcpy(new_fid->path, fid->path);
+		/* skip the space for count */
+		pdu->write_offset += sizeof(u16);
+		for (i = 0; i < nwname; i++) {
+			struct stat st;
+			char tmp[PATH_MAX] = {0};
+			char full_path[PATH_MAX];
+			char *str;
+
+			virtio_p9_pdu_readf(pdu, "s", &str);
+
+			/* Format the new path we're 'walk'ing into */
+			sprintf(tmp, "%s/%s", new_fid->path, str);
+
+			free(str);
+
+			if (lstat(rel_to_abs(p9dev, tmp, full_path), &st) < 0)
+				goto err_out;
+
+			stat2qid(&st, &wqid);
+			new_fid->is_dir = S_ISDIR(st.st_mode);
+			strcpy(new_fid->path, tmp);
+			new_fid->fid = newfid_val;
+			new_fid->uid = fid->uid;
+			nwqid++;
+			virtio_p9_pdu_writef(pdu, "Q", &wqid);
+		}
+	} else {
+		/*
+		 * update write_offset so our outlen get correct value
+		 */
+		pdu->write_offset += sizeof(u16);
+		new_fid->is_dir = p9dev->fids[fid_val].is_dir;
+		strcpy(new_fid->path, p9dev->fids[fid_val].path);
+		new_fid->fid	= newfid_val;
+		new_fid->uid    = p9dev->fids[fid_val].uid;
+	}
+	*outlen = pdu->write_offset;
+	pdu->write_offset = VIRTIO_P9_HDR_LEN;
+	virtio_p9_pdu_writef(pdu, "d", nwqid);
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_attach(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
+{
+	int i;
+	char *uname;
+	char *aname;
+	struct stat st;
+	struct p9_qid qid;
+	struct p9_fid *fid;
+	u32 fid_val, afid, uid;
+
+	virtio_p9_pdu_readf(pdu, "ddssd", &fid_val, &afid,
+			    &uname, &aname, &uid);
+
+	free(uname);
+	free(aname);
+
+	/* Reset everything */
+	for (i = 0; i < VIRTIO_P9_MAX_FID; i++)
+		p9dev->fids[i].fid = P9_NOFID;
+
+	if (lstat(p9dev->root_dir, &st) < 0)
+		goto err_out;
+
+	stat2qid(&st, &qid);
+
+	fid = &p9dev->fids[fid_val];
+	fid->fid = fid_val;
+	fid->uid = uid;
+	fid->is_dir = 1;
+	strcpy(fid->path, "/");
+
+	virtio_p9_pdu_writef(pdu, "Q", &qid);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_fill_stat(struct p9_dev *p9dev,
+				struct stat *st, struct p9_stat_dotl *statl)
+{
+	memset(statl, 0, sizeof(*statl));
+	statl->st_mode = st->st_mode;
+	statl->st_nlink = st->st_nlink;
+	statl->st_uid = st->st_uid;
+	statl->st_gid = st->st_gid;
+	statl->st_rdev = st->st_rdev;
+	statl->st_size = st->st_size;
+	statl->st_blksize = st->st_blksize;
+	statl->st_blocks = st->st_blocks;
+	statl->st_atime_sec = st->st_atime;
+	statl->st_atime_nsec = st->st_atim.tv_nsec;
+	statl->st_mtime_sec = st->st_mtime;
+	statl->st_mtime_nsec = st->st_mtim.tv_nsec;
+	statl->st_ctime_sec = st->st_ctime;
+	statl->st_ctime_nsec = st->st_ctim.tv_nsec;
+	/* Currently we only support BASIC fields in stat */
+	statl->st_result_mask = P9_STATS_BASIC;
+	stat2qid(st, &statl->qid);
+}
+
+static void virtio_p9_read(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
+{
+	u64 offset;
+	u32 fid_val;
+	u16 iov_cnt;
+	void *iov_base;
+	size_t iov_len;
+	u32 count, rcount;
+	struct p9_fid *fid;
+
+
+	rcount = 0;
+	virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+	fid = &p9dev->fids[fid_val];
+
+	iov_base = pdu->in_iov[0].iov_base;
+	iov_len  = pdu->in_iov[0].iov_len;
+	iov_cnt  = pdu->in_iov_cnt;
+	pdu->in_iov[0].iov_base += VIRTIO_P9_HDR_LEN + sizeof(u32);
+	pdu->in_iov[0].iov_len -= VIRTIO_P9_HDR_LEN + sizeof(u32);
+	pdu->in_iov_cnt = virtio_p9_update_iov_cnt(pdu->in_iov,
+						   count,
+						   pdu->in_iov_cnt);
+	rcount = preadv(fid->fd, pdu->in_iov,
+			pdu->in_iov_cnt, offset);
+	if (rcount > count)
+		rcount = count;
+	/*
+	 * Update the iov_base back, so that rest of
+	 * pdu_writef works correctly.
+	 */
+	pdu->in_iov[0].iov_base = iov_base;
+	pdu->in_iov[0].iov_len  = iov_len;
+	pdu->in_iov_cnt         = iov_cnt;
+
+	pdu->write_offset = VIRTIO_P9_HDR_LEN;
+	virtio_p9_pdu_writef(pdu, "d", rcount);
+	*outlen = pdu->write_offset + rcount;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+}
+
+static int virtio_p9_dentry_size(struct dirent *dent)
+{
+	/*
+	 * Size of each dirent:
+	 * qid(13) + offset(8) + type(1) + name_len(2) + name
+	 */
+	return 24 + strlen(dent->d_name);
+}
+
+static void virtio_p9_readdir(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 fid_val;
+	u32 count, rcount;
+	struct stat st;
+	struct p9_fid *fid;
+	struct dirent *dent;
+	char full_path[PATH_MAX];
+	u64 offset, old_offset;
+
+	rcount = 0;
+	virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+	fid = &p9dev->fids[fid_val];
+
+	if (!fid->is_dir) {
+		errno = -EINVAL;
+		goto err_out;
+	}
+
+	/* Move the offset specified */
+	seekdir(fid->dir, offset);
+
+	old_offset = offset;
+	/* If reading a dir, fill the buffer with p9_stat entries */
+	dent = readdir(fid->dir);
+
+	/* Skip the space for writing count */
+	pdu->write_offset += sizeof(u32);
+	while (dent) {
+		u32 read;
+		struct p9_qid qid;
+
+		if ((rcount + virtio_p9_dentry_size(dent)) > count) {
+			/* seek to the previous offset and return */
+			seekdir(fid->dir, old_offset);
+			break;
+		}
+		old_offset = dent->d_off;
+		lstat(rel_to_abs(p9dev, dent->d_name, full_path), &st);
+		stat2qid(&st, &qid);
+		read = pdu->write_offset;
+		virtio_p9_pdu_writef(pdu, "Qqbs", &qid, dent->d_off,
+				     dent->d_type, dent->d_name);
+		rcount += pdu->write_offset - read;
+		dent = readdir(fid->dir);
+	}
+
+	pdu->write_offset = VIRTIO_P9_HDR_LEN;
+	virtio_p9_pdu_writef(pdu, "d", rcount);
+	*outlen = pdu->write_offset + rcount;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+
+static void virtio_p9_getattr(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 fid_val;
+	struct stat st;
+	u64 request_mask;
+	struct p9_fid *fid;
+	struct p9_stat_dotl statl;
+
+	virtio_p9_pdu_readf(pdu, "dq", &fid_val, &request_mask);
+	fid = &p9dev->fids[fid_val];
+	if (lstat(fid->abs_path, &st) < 0)
+		goto err_out;
+
+	virtio_p9_fill_stat(p9dev, &st, &statl);
+	virtio_p9_pdu_writef(pdu, "A", &statl);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+/* FIXME!! from linux/fs.h */
+/*
+ * Attribute flags.  These should be or-ed together to figure out what
+ * has been changed!
+ */
+#define ATTR_MODE	(1 << 0)
+#define ATTR_UID	(1 << 1)
+#define ATTR_GID	(1 << 2)
+#define ATTR_SIZE	(1 << 3)
+#define ATTR_ATIME	(1 << 4)
+#define ATTR_MTIME	(1 << 5)
+#define ATTR_CTIME	(1 << 6)
+#define ATTR_ATIME_SET	(1 << 7)
+#define ATTR_MTIME_SET	(1 << 8)
+#define ATTR_FORCE	(1 << 9) /* Not a change, but a change it */
+#define ATTR_ATTR_FLAG	(1 << 10)
+#define ATTR_KILL_SUID	(1 << 11)
+#define ATTR_KILL_SGID	(1 << 12)
+#define ATTR_FILE	(1 << 13)
+#define ATTR_KILL_PRIV	(1 << 14)
+#define ATTR_OPEN	(1 << 15) /* Truncating from open(O_TRUNC) */
+#define ATTR_TIMES_SET	(1 << 16)
+
+#define ATTR_MASK    127
+
+static void virtio_p9_setattr(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret = 0;
+	u32 fid_val;
+	struct p9_fid *fid;
+	struct p9_iattr_dotl p9attr;
+
+	virtio_p9_pdu_readf(pdu, "dI", &fid_val, &p9attr);
+	fid = &p9dev->fids[fid_val];
+
+	if (p9attr.valid & ATTR_MODE) {
+		ret = chmod(fid->abs_path, p9attr.mode);
+		if (ret < 0)
+			goto err_out;
+	}
+	if (p9attr.valid & (ATTR_ATIME | ATTR_MTIME)) {
+		struct timespec times[2];
+		if (p9attr.valid & ATTR_ATIME) {
+			if (p9attr.valid & ATTR_ATIME_SET) {
+				times[0].tv_sec = p9attr.atime_sec;
+				times[0].tv_nsec = p9attr.atime_nsec;
+			} else {
+				times[0].tv_nsec = UTIME_NOW;
+			}
+		} else {
+			times[0].tv_nsec = UTIME_OMIT;
+		}
+		if (p9attr.valid & ATTR_MTIME) {
+			if (p9attr.valid & ATTR_MTIME_SET) {
+				times[1].tv_sec = p9attr.mtime_sec;
+				times[1].tv_nsec = p9attr.mtime_nsec;
+			} else {
+				times[1].tv_nsec = UTIME_NOW;
+			}
+		} else
+			times[1].tv_nsec = UTIME_OMIT;
+
+		ret = utimensat(-1, fid->abs_path, times, AT_SYMLINK_NOFOLLOW);
+		if (ret < 0)
+			goto err_out;
+	}
+	/*
+	 * If the only valid entry in iattr is ctime we can call
+	 * chown(-1,-1) to update the ctime of the file
+	 */
+	if ((p9attr.valid & (ATTR_UID | ATTR_GID)) ||
+	    ((p9attr.valid & ATTR_CTIME)
+	     && !((p9attr.valid & ATTR_MASK) & ~ATTR_CTIME))) {
+		if (!(p9attr.valid & ATTR_UID))
+			p9attr.uid = -1;
+
+		if (!(p9attr.valid & ATTR_GID))
+			p9attr.gid = -1;
+
+		ret = lchown(fid->abs_path, p9attr.uid, p9attr.gid);
+		if (ret < 0)
+			goto err_out;
+	}
+	if (p9attr.valid & (ATTR_SIZE)) {
+		ret = truncate(fid->abs_path, p9attr.size);
+		if (ret < 0)
+			goto err_out;
+	}
+	*outlen = VIRTIO_P9_HDR_LEN;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_write(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
+{
+
+	u64 offset;
+	u32 fid_val;
+	u32 count;
+	ssize_t res;
+	u16 iov_cnt;
+	void *iov_base;
+	size_t iov_len;
+	struct p9_fid *fid;
+	/* u32 fid + u64 offset + u32 count */
+	int twrite_size = sizeof(u32) + sizeof(u64) + sizeof(u32);
+
+	virtio_p9_pdu_readf(pdu, "dqd", &fid_val, &offset, &count);
+	fid = &p9dev->fids[fid_val];
+
+	iov_base = pdu->out_iov[0].iov_base;
+	iov_len  = pdu->out_iov[0].iov_len;
+	iov_cnt  = pdu->out_iov_cnt;
+
+	/* Adjust the iovec to skip the header and meta data */
+	pdu->out_iov[0].iov_base += (sizeof(struct p9_msg) + twrite_size);
+	pdu->out_iov[0].iov_len -=  (sizeof(struct p9_msg) + twrite_size);
+	pdu->out_iov_cnt = virtio_p9_update_iov_cnt(pdu->out_iov, count,
+						    pdu->out_iov_cnt);
+	res = pwritev(fid->fd, pdu->out_iov, pdu->out_iov_cnt, offset);
+	/*
+	 * Update the iov_base back, so that rest of
+	 * pdu_readf works correctly.
+	 */
+	pdu->out_iov[0].iov_base = iov_base;
+	pdu->out_iov[0].iov_len  = iov_len;
+	pdu->out_iov_cnt         = iov_cnt;
+
+	if (res < 0)
+		goto err_out;
+	virtio_p9_pdu_writef(pdu, "d", res);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_remove(struct p9_dev *p9dev,
+			       struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	u32 fid_val;
+	struct p9_fid *fid;
+
+	virtio_p9_pdu_readf(pdu, "d", &fid_val);
+	fid = &p9dev->fids[fid_val];
+
+	ret = remove(fid->abs_path);
+	if (ret < 0)
+		goto err_out;
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_rename(struct p9_dev *p9dev,
+			       struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	u32 fid_val, new_fid_val;
+	struct p9_fid *fid, *new_fid;
+	char full_path[PATH_MAX], *new_name;
+
+	virtio_p9_pdu_readf(pdu, "dds", &fid_val, &new_fid_val, &new_name);
+	fid = &p9dev->fids[fid_val];
+	new_fid = &p9dev->fids[new_fid_val];
+
+	sprintf(full_path, "%s/%s", new_fid->abs_path, new_name);
+	ret = rename(fid->abs_path, full_path);
+	if (ret < 0)
+		goto err_out;
+	close_fid(p9dev, fid_val);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_readlink(struct p9_dev *p9dev,
+			       struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	u32 fid_val;
+	struct p9_fid *fid;
+	char target_path[PATH_MAX];
+
+	virtio_p9_pdu_readf(pdu, "d", &fid_val);
+	fid = &p9dev->fids[fid_val];
+
+	memset(target_path, 0, PATH_MAX);
+	ret = readlink(fid->abs_path, target_path, PATH_MAX - 1);
+	if (ret < 0)
+		goto err_out;
+
+	virtio_p9_pdu_writef(pdu, "s", target_path);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_statfs(struct p9_dev *p9dev,
+			     struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	u64 fsid;
+	u32 fid_val;
+	struct p9_fid *fid;
+	struct statfs stat_buf;
+
+	virtio_p9_pdu_readf(pdu, "d", &fid_val);
+	fid = &p9dev->fids[fid_val];
+
+	ret = statfs(fid->abs_path, &stat_buf);
+	if (ret < 0)
+		goto err_out;
+	/* FIXME!! f_blocks needs update based on client msize */
+	fsid = (unsigned int) stat_buf.f_fsid.__val[0] |
+		(unsigned long long)stat_buf.f_fsid.__val[1] << 32;
+	virtio_p9_pdu_writef(pdu, "ddqqqqqqd", stat_buf.f_type,
+			     stat_buf.f_bsize, stat_buf.f_blocks,
+			     stat_buf.f_bfree, stat_buf.f_bavail,
+			     stat_buf.f_files, stat_buf.f_ffree,
+			     fsid, stat_buf.f_namelen);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_mknod(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	char *name;
+	struct stat st;
+	struct p9_fid *dfid;
+	struct p9_qid qid;
+	char full_path[PATH_MAX];
+	u32 fid_val, mode, major, minor, gid;
+
+	virtio_p9_pdu_readf(pdu, "dsdddd", &fid_val, &name, &mode,
+			    &major, &minor, &gid);
+
+	dfid = &p9dev->fids[fid_val];
+	sprintf(full_path, "%s/%s", dfid->abs_path, name);
+	ret = mknod(full_path, mode, makedev(major, minor));
+	if (ret < 0)
+		goto err_out;
+
+	if (lstat(full_path, &st) < 0)
+		goto err_out;
+
+	ret = chmod(full_path, mode & 0777);
+	if (ret < 0)
+		goto err_out;
+
+	ret = lchown(full_path, dfid->uid, gid);
+	if (ret < 0)
+		goto err_out;
+
+	stat2qid(&st, &qid);
+	virtio_p9_pdu_writef(pdu, "Q", &qid);
+	free(name);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	free(name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_fsync(struct p9_dev *p9dev,
+			    struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	struct p9_fid *fid;
+	u32 fid_val, datasync;
+
+	virtio_p9_pdu_readf(pdu, "dd", &fid_val, &datasync);
+	fid = &p9dev->fids[fid_val];
+
+	if (datasync)
+		ret = fdatasync(fid->fd);
+	else
+		ret = fsync(fid->fd);
+	if (ret < 0)
+		goto err_out;
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_symlink(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	struct stat st;
+	u32 fid_val, gid;
+	struct p9_qid qid;
+	struct p9_fid *dfid;
+	char new_name[PATH_MAX];
+	char *old_path, *name;
+
+	virtio_p9_pdu_readf(pdu, "dssd", &fid_val, &name, &old_path, &gid);
+
+	dfid = &p9dev->fids[fid_val];
+	sprintf(new_name, "%s/%s", dfid->abs_path, name);
+	ret = symlink(old_path, new_name);
+	if (ret < 0)
+		goto err_out;
+
+	if (lstat(new_name, &st) < 0)
+		goto err_out;
+
+	ret = lchown(new_name, dfid->uid, gid);
+	if (ret < 0)
+		goto err_out;
+
+	stat2qid(&st, &qid);
+	virtio_p9_pdu_writef(pdu, "Q", &qid);
+	free(name);
+	free(old_path);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	free(name);
+	free(old_path);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_link(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	char *name;
+	u32 fid_val, dfid_val;
+	struct p9_fid *dfid, *fid;
+	char full_path[PATH_MAX];
+
+	virtio_p9_pdu_readf(pdu, "dds", &dfid_val, &fid_val, &name);
+
+	dfid = &p9dev->fids[dfid_val];
+	fid =  &p9dev->fids[fid_val];
+	sprintf(full_path, "%s/%s", dfid->abs_path, name);
+	ret = link(fid->abs_path, full_path);
+	if (ret < 0)
+		goto err_out;
+	free(name);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	free(name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+
+}
+
+static void virtio_p9_lock(struct p9_dev *p9dev,
+			   struct p9_pdu *pdu, u32 *outlen)
+{
+	u8 ret;
+	u32 fid_val;
+	struct p9_flock flock;
+
+	virtio_p9_pdu_readf(pdu, "dbdqqds", &fid_val, &flock.type,
+			    &flock.flags, &flock.start, &flock.length,
+			    &flock.proc_id, &flock.client_id);
+
+	/* Just return success */
+	ret = P9_LOCK_SUCCESS;
+	virtio_p9_pdu_writef(pdu, "d", ret);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	free(flock.client_id);
+	return;
+}
+
+static void virtio_p9_getlock(struct p9_dev *p9dev,
+			      struct p9_pdu *pdu, u32 *outlen)
+{
+	u32 fid_val;
+	struct p9_getlock glock;
+	virtio_p9_pdu_readf(pdu, "dbqqds", &fid_val, &glock.type,
+			    &glock.start, &glock.length, &glock.proc_id,
+			    &glock.client_id);
+
+	/* Just return success */
+	glock.type = F_UNLCK;
+	virtio_p9_pdu_writef(pdu, "bqqds", glock.type,
+			     glock.start, glock.length, glock.proc_id,
+			     glock.client_id);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	free(glock.client_id);
+	return;
+}
+
+static int virtio_p9_ancestor(char *path, char *ancestor)
+{
+	int size = strlen(ancestor);
+	if (!strncmp(path, ancestor, size)) {
+		/*
+		 * Now check whether ancestor is a full name or
+		 * or directory component and not just part
+		 * of a name.
+		 */
+		if (path[size] == '\0' || path[size] == '/')
+			return 1;
+	}
+	return 0;
+}
+
+static void virtio_p9_fix_path(char *fid_path, char *old_name, char *new_name)
+{
+	char tmp_name[PATH_MAX];
+	size_t rp_sz = strlen(old_name);
+
+	if (rp_sz == strlen(fid_path)) {
+		/* replace the full name */
+		strcpy(fid_path, new_name);
+		return;
+	}
+	/* save the trailing path details */
+	strcpy(tmp_name, fid_path + rp_sz);
+	sprintf(fid_path, "%s%s", new_name, tmp_name);
+	return;
+}
+
+static void virtio_p9_renameat(struct p9_dev *p9dev,
+			       struct p9_pdu *pdu, u32 *outlen)
+{
+	int i, ret;
+	char *old_name, *new_name;
+	u32 old_dfid_val, new_dfid_val;
+	struct p9_fid *old_dfid, *new_dfid;
+	char old_full_path[PATH_MAX], new_full_path[PATH_MAX];
+
+
+	virtio_p9_pdu_readf(pdu, "dsds", &old_dfid_val, &old_name,
+			    &new_dfid_val, &new_name);
+
+	old_dfid = &p9dev->fids[old_dfid_val];
+	new_dfid = &p9dev->fids[new_dfid_val];
+
+	sprintf(old_full_path, "%s/%s", old_dfid->abs_path, old_name);
+	sprintf(new_full_path, "%s/%s", new_dfid->abs_path, new_name);
+	ret = rename(old_full_path, new_full_path);
+	if (ret < 0)
+		goto err_out;
+	/*
+	 * Now fix path in other fids, if the renamed path is part of
+	 * that.
+	 */
+	for (i = 0; i < VIRTIO_P9_MAX_FID; i++) {
+		if (p9dev->fids[i].fid != P9_NOFID &&
+		    virtio_p9_ancestor(p9dev->fids[i].path, old_name)) {
+			virtio_p9_fix_path(p9dev->fids[i].path, old_name,
+					   new_name);
+		}
+	}
+	free(old_name);
+	free(new_name);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	free(old_name);
+	free(new_name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_unlinkat(struct p9_dev *p9dev,
+			       struct p9_pdu *pdu, u32 *outlen)
+{
+	int ret;
+	char *name;
+	u32 fid_val, flags;
+	struct p9_fid *fid;
+	char full_path[PATH_MAX];
+
+	virtio_p9_pdu_readf(pdu, "dsd", &fid_val, &name, &flags);
+	fid = &p9dev->fids[fid_val];
+
+	sprintf(full_path, "%s/%s", fid->abs_path, name);
+	ret = remove(full_path);
+	if (ret < 0)
+		goto err_out;
+	free(name);
+	*outlen = pdu->write_offset;
+	virtio_p9_set_reply_header(pdu, *outlen);
+	return;
+err_out:
+	free(name);
+	virtio_p9_error_reply(p9dev, pdu, errno, outlen);
+	return;
+}
+
+static void virtio_p9_eopnotsupp(struct p9_dev *p9dev,
+				 struct p9_pdu *pdu, u32 *outlen)
+{
+	return virtio_p9_error_reply(p9dev, pdu, EOPNOTSUPP, outlen);
+}
+
+typedef void p9_handler(struct p9_dev *p9dev,
+			struct p9_pdu *pdu, u32 *outlen);
+
+/* FIXME should be removed when merging with latest linus tree */
+#define P9_TRENAMEAT 74
+#define P9_TUNLINKAT 76
+
+static p9_handler *virtio_9p_dotl_handler [] = {
+	[P9_TREADDIR]     = virtio_p9_readdir,
+	[P9_TSTATFS]      = virtio_p9_statfs,
+	[P9_TGETATTR]     = virtio_p9_getattr,
+	[P9_TSETATTR]     = virtio_p9_setattr,
+	[P9_TXATTRWALK]   = virtio_p9_eopnotsupp,
+	[P9_TXATTRCREATE] = virtio_p9_eopnotsupp,
+	[P9_TMKNOD]       = virtio_p9_mknod,
+	[P9_TLOCK]        = virtio_p9_lock,
+	[P9_TGETLOCK]     = virtio_p9_getlock,
+	[P9_TRENAMEAT]    = virtio_p9_renameat,
+	[P9_TREADLINK]    = virtio_p9_readlink,
+	[P9_TUNLINKAT]    = virtio_p9_unlinkat,
+	[P9_TMKDIR]       = virtio_p9_mkdir,
+	[P9_TVERSION]     = virtio_p9_version,
+	[P9_TLOPEN]       = virtio_p9_open,
+	[P9_TATTACH]      = virtio_p9_attach,
+	[P9_TWALK]        = virtio_p9_walk,
+	[P9_TCLUNK]       = virtio_p9_clunk,
+	[P9_TFSYNC]       = virtio_p9_fsync,
+	[P9_TREAD]        = virtio_p9_read,
+	[P9_TFLUSH]       = virtio_p9_eopnotsupp,
+	[P9_TLINK]        = virtio_p9_link,
+	[P9_TSYMLINK]     = virtio_p9_symlink,
+	[P9_TLCREATE]     = virtio_p9_create,
+	[P9_TWRITE]       = virtio_p9_write,
+	[P9_TREMOVE]      = virtio_p9_remove,
+	[P9_TRENAME]      = virtio_p9_rename,
+};
+
+static struct p9_pdu *virtio_p9_pdu_init(struct kvm *kvm, struct virt_queue *vq)
+{
+	struct p9_pdu *pdu = calloc(1, sizeof(*pdu));
+	if (!pdu)
+		return NULL;
+
+	/* skip the pdu header p9_msg */
+	pdu->read_offset  = VIRTIO_P9_HDR_LEN;
+	pdu->write_offset = VIRTIO_P9_HDR_LEN;
+	pdu->queue_head  = virt_queue__get_inout_iov(kvm, vq, pdu->in_iov,
+						     pdu->out_iov,
+						     &pdu->in_iov_cnt,
+						     &pdu->out_iov_cnt);
+	return pdu;
+}
+
+static u8 virtio_p9_get_cmd(struct p9_pdu *pdu)
+{
+	struct p9_msg *msg;
+	/*
+	 * we can peek directly into pdu for a u8
+	 * value. The host endianess won't be an issue
+	 */
+	msg = pdu->out_iov[0].iov_base;
+	return msg->cmd;
+}
+
+static bool virtio_p9_do_io_request(struct kvm *kvm, struct p9_dev_job *job)
+{
+	u8 cmd;
+	u32 len = 0;
+	p9_handler *handler;
+	struct p9_dev *p9dev;
+	struct virt_queue *vq;
+	struct p9_pdu *p9pdu;
+
+	vq = job->vq;
+	p9dev = job->p9dev;
+
+	p9pdu = virtio_p9_pdu_init(kvm, vq);
+	cmd = virtio_p9_get_cmd(p9pdu);
+
+	if ((cmd >= ARRAY_SIZE(virtio_9p_dotl_handler)) ||
+	    !virtio_9p_dotl_handler[cmd])
+		handler = virtio_p9_eopnotsupp;
+	else
+		handler = virtio_9p_dotl_handler[cmd];
+
+	handler(p9dev, p9pdu, &len);
+	virt_queue__set_used_elem(vq, p9pdu->queue_head, len);
+	free(p9pdu);
+	return true;
+}
+
+static void virtio_p9_do_io(struct kvm *kvm, void *param)
+{
+	struct p9_dev_job *job = (struct p9_dev_job *)param;
+	struct p9_dev *p9dev   = job->p9dev;
+	struct virt_queue *vq  = job->vq;
+
+	while (virt_queue__available(vq)) {
+		virtio_p9_do_io_request(kvm, job);
+		p9dev->vtrans.trans_ops->signal_vq(kvm, &p9dev->vtrans, vq - p9dev->vqs);
+	}
+}
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct p9_dev *p9dev = dev;
+
+	((u8 *)(p9dev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct p9_dev *p9dev = dev;
+
+	return ((u8 *)(p9dev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1 << VIRTIO_9P_MOUNT_TAG;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct p9_dev *p9dev = dev;
+
+	p9dev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct p9_dev *p9dev = dev;
+	struct p9_dev_job *job;
+	struct virt_queue *queue;
+	void *p;
+
+	compat__remove_message(compat_id);
+
+	queue			= &p9dev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+	job			= &p9dev->jobs[vq];
+
+	vring_init(&queue->vring, VIRTQUEUE_NUM, p, VIRTIO_PCI_VRING_ALIGN);
+
+	*job			= (struct p9_dev_job) {
+		.vq			= queue,
+		.p9dev			= p9dev,
+	};
+	thread_pool__init_job(&job->job_id, kvm, virtio_p9_do_io, job);
+
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct p9_dev *p9dev = dev;
+
+	thread_pool__do_job(&p9dev->jobs[vq].job_id);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct p9_dev *p9dev = dev;
+
+	return p9dev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTQUEUE_NUM;
+}
+
+struct virtio_ops p9_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+};
+
+int virtio_9p__init(struct kvm *kvm)
+{
+	struct p9_dev *p9dev;
+
+	list_for_each_entry(p9dev, &devs, list) {
+		virtio_trans_init(&p9dev->vtrans, VIRTIO_PCI);
+		p9dev->vtrans.trans_ops->init(kvm, &p9dev->vtrans, p9dev,
+					PCI_DEVICE_ID_VIRTIO_P9, VIRTIO_ID_9P, PCI_CLASS_P9);
+		p9dev->vtrans.virtio_ops = &p9_dev_virtio_ops;
+	}
+
+	return 0;
+}
+
+int virtio_9p__register(struct kvm *kvm, const char *root, const char *tag_name)
+{
+	struct p9_dev *p9dev;
+	u32 i, root_len;
+	int err = 0;
+
+	p9dev = calloc(1, sizeof(*p9dev));
+	if (!p9dev)
+		return -ENOMEM;
+
+	if (!tag_name)
+		tag_name = VIRTIO_P9_DEFAULT_TAG;
+
+	p9dev->config = calloc(1, sizeof(*p9dev->config) + strlen(tag_name) + 1);
+	if (p9dev->config == NULL) {
+		err = -ENOMEM;
+		goto free_p9dev;
+	}
+
+	strcpy(p9dev->root_dir, root);
+	root_len = strlen(root);
+	/*
+	 * We prefix the full path in all fids, This allows us to get the
+	 * absolute path of an fid without playing with strings.
+	 */
+	for (i = 0; i < VIRTIO_P9_MAX_FID; i++) {
+		strcpy(p9dev->fids[i].abs_path, root);
+		p9dev->fids[i].path = p9dev->fids[i].abs_path + root_len;
+	}
+	p9dev->config->tag_len = strlen(tag_name);
+	if (p9dev->config->tag_len > MAX_TAG_LEN) {
+		err = -EINVAL;
+		goto free_p9dev_config;
+	}
+
+	memcpy(&p9dev->config->tag, tag_name, strlen(tag_name));
+
+	list_add(&p9dev->list, &devs);
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-9p device was not detected",
+						"While you have requested a virtio-9p device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_NET_9P_VIRTIO=y enabled "
+						"in its .config");
+
+	return err;
+
+free_p9dev_config:
+	free(p9dev->config);
+free_p9dev:
+	free(p9dev);
+	return err;
+}
diff --git a/tools/kvm/virtio/balloon.c b/tools/kvm/virtio/balloon.c
new file mode 100644
index 0000000..09044d0
--- /dev/null
+++ b/tools/kvm/virtio/balloon.c
@@ -0,0 +1,275 @@
+#include "kvm/virtio-balloon.h"
+
+#include "kvm/virtio-pci-dev.h"
+
+#include "kvm/virtio.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-trans.h"
+#include "kvm/kvm-ipc.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_balloon.h>
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <sys/eventfd.h>
+
+#define NUM_VIRT_QUEUES		3
+#define VIRTIO_BLN_QUEUE_SIZE	128
+#define VIRTIO_BLN_INFLATE	0
+#define VIRTIO_BLN_DEFLATE	1
+#define VIRTIO_BLN_STATS	2
+
+struct bln_dev {
+	struct list_head	list;
+	struct virtio_trans	vtrans;
+
+	u32			features;
+
+	/* virtio queue */
+	struct virt_queue	vqs[NUM_VIRT_QUEUES];
+	struct thread_pool__job	jobs[NUM_VIRT_QUEUES];
+
+	struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
+	struct virtio_balloon_stat *cur_stat;
+	u32			cur_stat_head;
+	u16			stat_count;
+	int			stat_waitfd;
+
+	struct virtio_balloon_config config;
+};
+
+static struct bln_dev bdev;
+extern struct kvm *kvm;
+static int compat_id = -1;
+
+static bool virtio_bln_do_io_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+	struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+	unsigned int len = 0;
+	u16 out, in, head;
+	u32 *ptrs, i;
+
+	head	= virt_queue__get_iov(queue, iov, &out, &in, kvm);
+	ptrs	= iov[0].iov_base;
+	len	= iov[0].iov_len / sizeof(u32);
+
+	for (i = 0 ; i < len ; i++) {
+		void *guest_ptr;
+
+		guest_ptr = guest_flat_to_host(kvm, ptrs[i] << VIRTIO_BALLOON_PFN_SHIFT);
+		if (queue == &bdev->vqs[VIRTIO_BLN_INFLATE]) {
+			madvise(guest_ptr, 1 << VIRTIO_BALLOON_PFN_SHIFT, MADV_DONTNEED);
+			bdev->config.actual++;
+		} else if (queue == &bdev->vqs[VIRTIO_BLN_DEFLATE]) {
+			bdev->config.actual--;
+		}
+	}
+
+	virt_queue__set_used_elem(queue, head, len);
+
+	return true;
+}
+
+static bool virtio_bln_do_stat_request(struct kvm *kvm, struct bln_dev *bdev, struct virt_queue *queue)
+{
+	struct iovec iov[VIRTIO_BLN_QUEUE_SIZE];
+	u16 out, in, head;
+	struct virtio_balloon_stat *stat;
+	u64 wait_val = 1;
+
+	head = virt_queue__get_iov(queue, iov, &out, &in, kvm);
+	stat = iov[0].iov_base;
+
+	/* Initial empty stat buffer */
+	if (bdev->cur_stat == NULL) {
+		bdev->cur_stat = stat;
+		bdev->cur_stat_head = head;
+
+		return true;
+	}
+
+	memcpy(bdev->stats, stat, iov[0].iov_len);
+
+	bdev->stat_count = iov[0].iov_len / sizeof(struct virtio_balloon_stat);
+	bdev->cur_stat = stat;
+	bdev->cur_stat_head = head;
+
+	if (write(bdev->stat_waitfd, &wait_val, sizeof(wait_val)) <= 0)
+		return -EFAULT;
+
+	return 1;
+}
+
+static void virtio_bln_do_io(struct kvm *kvm, void *param)
+{
+	struct virt_queue *vq = param;
+
+	if (vq == &bdev.vqs[VIRTIO_BLN_STATS]) {
+		virtio_bln_do_stat_request(kvm, &bdev, vq);
+		bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, VIRTIO_BLN_STATS);
+		return;
+	}
+
+	while (virt_queue__available(vq)) {
+		virtio_bln_do_io_request(kvm, &bdev, vq);
+		bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, vq - bdev.vqs);
+	}
+}
+
+static int virtio_bln__collect_stats(void)
+{
+	u64 tmp;
+
+	virt_queue__set_used_elem(&bdev.vqs[VIRTIO_BLN_STATS], bdev.cur_stat_head,
+				  sizeof(struct virtio_balloon_stat));
+	bdev.vtrans.trans_ops->signal_vq(kvm, &bdev.vtrans, VIRTIO_BLN_STATS);
+
+	if (read(bdev.stat_waitfd, &tmp, sizeof(tmp)) <= 0)
+		return -EFAULT;
+
+	return 0;
+}
+
+static void virtio_bln__print_stats(int fd, u32 type, u32 len, u8 *msg)
+{
+	int r;
+
+	if (WARN_ON(type != KVM_IPC_STAT || len))
+		return;
+
+	if (virtio_bln__collect_stats() < 0)
+		return;
+
+	r = write(fd, bdev.stats, sizeof(bdev.stats));
+	if (r < 0)
+		pr_warning("Failed sending memory stats");
+}
+
+static void handle_mem(int fd, u32 type, u32 len, u8 *msg)
+{
+	int mem;
+
+	if (WARN_ON(type != KVM_IPC_BALLOON || len != sizeof(int)))
+		return;
+
+	mem = *(int *)msg;
+	if (mem > 0) {
+		bdev.config.num_pages += 256 * mem;
+	} else if (mem < 0) {
+		if (bdev.config.num_pages < (u32)(256 * (-mem)))
+			return;
+
+		bdev.config.num_pages += 256 * mem;
+	}
+
+	/* Notify that the configuration space has changed */
+	bdev.vtrans.trans_ops->signal_config(kvm, &bdev.vtrans);
+}
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct bln_dev *bdev = dev;
+
+	((u8 *)(&bdev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct bln_dev *bdev = dev;
+
+	return ((u8 *)(&bdev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1 << VIRTIO_BALLOON_F_STATS_VQ;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct bln_dev *bdev = dev;
+
+	bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct bln_dev *bdev = dev;
+	struct virt_queue *queue;
+	void *p;
+
+	compat__remove_message(compat_id);
+
+	queue			= &bdev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	thread_pool__init_job(&bdev->jobs[vq], kvm, virtio_bln_do_io, queue);
+	vring_init(&queue->vring, VIRTIO_BLN_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct bln_dev *bdev = dev;
+
+	thread_pool__do_job(&bdev->jobs[vq]);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct bln_dev *bdev = dev;
+
+	return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_BLN_QUEUE_SIZE;
+}
+
+struct virtio_ops bln_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+};
+
+void virtio_bln__init(struct kvm *kvm)
+{
+	kvm_ipc__register_handler(KVM_IPC_BALLOON, handle_mem);
+	kvm_ipc__register_handler(KVM_IPC_STAT, virtio_bln__print_stats);
+
+	bdev.stat_waitfd	= eventfd(0, 0);
+	memset(&bdev.config, 0, sizeof(struct virtio_balloon_config));
+
+	virtio_trans_init(&bdev.vtrans, VIRTIO_PCI);
+	bdev.vtrans.trans_ops->init(kvm, &bdev.vtrans, &bdev, PCI_DEVICE_ID_VIRTIO_BLN,
+					VIRTIO_ID_BALLOON, PCI_CLASS_BLN);
+	bdev.vtrans.virtio_ops = &bln_dev_virtio_ops;
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-balloon device was not detected",
+						"While you have requested a virtio-balloon device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_VIRTIO_BALLOON=y enabled "
+						"in its .config");
+}
diff --git a/tools/kvm/virtio/blk.c b/tools/kvm/virtio/blk.c
new file mode 100644
index 0000000..1d921a8
--- /dev/null
+++ b/tools/kvm/virtio/blk.c
@@ -0,0 +1,273 @@
+#include "kvm/virtio-blk.h"
+
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/disk-image.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-pci.h"
+#include "kvm/virtio.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+#define VIRTIO_BLK_MAX_DEV		4
+
+/*
+ * the header and status consume too entries
+ */
+#define DISK_SEG_MAX			(VIRTIO_BLK_QUEUE_SIZE - 2)
+#define VIRTIO_BLK_QUEUE_SIZE		128
+#define NUM_VIRT_QUEUES			1
+
+struct blk_dev_req {
+	struct virt_queue		*vq;
+	struct blk_dev			*bdev;
+	struct iovec			iov[VIRTIO_BLK_QUEUE_SIZE];
+	u16				out, in, head;
+	struct kvm			*kvm;
+};
+
+struct blk_dev {
+	pthread_mutex_t			mutex;
+	pthread_mutex_t			req_mutex;
+
+	struct list_head		list;
+	struct list_head		req_list;
+
+	struct virtio_trans		vtrans;
+	struct virtio_blk_config	blk_config;
+	struct disk_image		*disk;
+	u32				features;
+
+	struct virt_queue		vqs[NUM_VIRT_QUEUES];
+	struct blk_dev_req		reqs[VIRTIO_BLK_QUEUE_SIZE];
+};
+
+static LIST_HEAD(bdevs);
+static int compat_id = -1;
+
+void virtio_blk_complete(void *param, long len)
+{
+	struct blk_dev_req *req = param;
+	struct blk_dev *bdev = req->bdev;
+	int queueid = req->vq - bdev->vqs;
+	u8 *status;
+
+	/* status */
+	status	= req->iov[req->out + req->in - 1].iov_base;
+	*status	= (len < 0) ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
+
+	mutex_lock(&bdev->mutex);
+	virt_queue__set_used_elem(req->vq, req->head, len);
+	mutex_unlock(&bdev->mutex);
+
+	if (virtio_queue__should_signal(&bdev->vqs[queueid]))
+		bdev->vtrans.trans_ops->signal_vq(req->kvm, &bdev->vtrans, queueid);
+}
+
+static void virtio_blk_do_io_request(struct kvm *kvm, struct blk_dev_req *req)
+{
+	struct virtio_blk_outhdr *req_hdr;
+	ssize_t block_cnt;
+	struct blk_dev *bdev;
+	struct iovec *iov;
+	u16 out, in;
+
+	block_cnt	= -1;
+	bdev		= req->bdev;
+	iov		= req->iov;
+	out		= req->out;
+	in		= req->in;
+	req_hdr		= iov[0].iov_base;
+
+	switch (req_hdr->type) {
+	case VIRTIO_BLK_T_IN:
+		block_cnt	= disk_image__read(bdev->disk, req_hdr->sector, iov + 1,
+					in + out - 2, req);
+		break;
+	case VIRTIO_BLK_T_OUT:
+		block_cnt	= disk_image__write(bdev->disk, req_hdr->sector, iov + 1,
+					in + out - 2, req);
+		break;
+	case VIRTIO_BLK_T_FLUSH:
+		block_cnt       = disk_image__flush(bdev->disk);
+		virtio_blk_complete(req, block_cnt);
+		break;
+	case VIRTIO_BLK_T_GET_ID:
+		block_cnt	= VIRTIO_BLK_ID_BYTES;
+		disk_image__get_serial(bdev->disk, (iov + 1)->iov_base, &block_cnt);
+		virtio_blk_complete(req, block_cnt);
+		break;
+	default:
+		pr_warning("request type %d", req_hdr->type);
+		block_cnt	= -1;
+		break;
+	}
+}
+
+static void virtio_blk_do_io(struct kvm *kvm, struct virt_queue *vq, struct blk_dev *bdev)
+{
+	struct blk_dev_req *req;
+	u16 head;
+
+	while (virt_queue__available(vq)) {
+		head		= virt_queue__pop(vq);
+		req		= &bdev->reqs[head];
+		req->head	= virt_queue__get_head_iov(vq, req->iov, &req->out, &req->in, head, kvm);
+		req->vq		= vq;
+
+		virtio_blk_do_io_request(kvm, req);
+	}
+}
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct blk_dev *bdev = dev;
+
+	((u8 *)(&bdev->blk_config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct blk_dev *bdev = dev;
+
+	return ((u8 *)(&bdev->blk_config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return	1UL << VIRTIO_BLK_F_SEG_MAX
+		| 1UL << VIRTIO_BLK_F_FLUSH
+		| 1UL << VIRTIO_RING_F_EVENT_IDX
+		| 1UL << VIRTIO_RING_F_INDIRECT_DESC;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct blk_dev *bdev = dev;
+
+	bdev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct blk_dev *bdev = dev;
+	struct virt_queue *queue;
+	void *p;
+
+	compat__remove_message(compat_id);
+
+	queue			= &bdev->vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	vring_init(&queue->vring, VIRTIO_BLK_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct blk_dev *bdev = dev;
+
+	virtio_blk_do_io(kvm, &bdev->vqs[vq], bdev);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct blk_dev *bdev = dev;
+
+	return bdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_BLK_QUEUE_SIZE;
+}
+
+static struct virtio_ops blk_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+};
+
+void virtio_blk__init(struct kvm *kvm, struct disk_image *disk)
+{
+	struct blk_dev *bdev;
+	unsigned int i;
+
+	if (!disk)
+		return;
+
+	bdev = calloc(1, sizeof(struct blk_dev));
+	if (bdev == NULL)
+		die("Failed allocating bdev");
+
+	*bdev = (struct blk_dev) {
+		.mutex			= PTHREAD_MUTEX_INITIALIZER,
+		.req_mutex		= PTHREAD_MUTEX_INITIALIZER,
+		.disk			= disk,
+		.blk_config		= (struct virtio_blk_config) {
+			.capacity	= disk->size / SECTOR_SIZE,
+			.seg_max	= DISK_SEG_MAX,
+		},
+	};
+
+	virtio_trans_init(&bdev->vtrans, VIRTIO_PCI);
+	bdev->vtrans.trans_ops->init(kvm, &bdev->vtrans, bdev, PCI_DEVICE_ID_VIRTIO_BLK,
+					VIRTIO_ID_BLOCK, PCI_CLASS_BLK);
+	bdev->vtrans.virtio_ops = &blk_dev_virtio_ops;
+
+	list_add_tail(&bdev->list, &bdevs);
+
+	for (i = 0; i < ARRAY_SIZE(bdev->reqs); i++) {
+		bdev->reqs[i].bdev	= bdev;
+		bdev->reqs[i].kvm	= kvm;
+	}
+
+	disk_image__set_callback(bdev->disk, virtio_blk_complete);
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-blk device was not detected",
+						"While you have requested a virtio-blk device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_VIRTIO_BLK=y enabled "
+						"in its .config");
+}
+
+void virtio_blk__init_all(struct kvm *kvm)
+{
+	int i;
+
+	for (i = 0; i < kvm->nr_disks; i++)
+		virtio_blk__init(kvm, kvm->disks[i]);
+}
+
+void virtio_blk__delete_all(struct kvm *kvm)
+{
+	while (!list_empty(&bdevs)) {
+		struct blk_dev *bdev;
+
+		bdev = list_first_entry(&bdevs, struct blk_dev, list);
+		list_del(&bdev->list);
+		free(bdev);
+	}
+}
diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
new file mode 100644
index 0000000..245cebb
--- /dev/null
+++ b/tools/kvm/virtio/console.c
@@ -0,0 +1,203 @@
+#include "kvm/virtio-console.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/disk-image.h"
+#include "kvm/virtio.h"
+#include "kvm/ioport.h"
+#include "kvm/util.h"
+#include "kvm/term.h"
+#include "kvm/mutex.h"
+#include "kvm/kvm.h"
+#include "kvm/pci.h"
+#include "kvm/threadpool.h"
+#include "kvm/irq.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/virtio_console.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_blk.h>
+
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#define VIRTIO_CONSOLE_QUEUE_SIZE	128
+#define VIRTIO_CONSOLE_NUM_QUEUES	2
+#define VIRTIO_CONSOLE_RX_QUEUE		0
+#define VIRTIO_CONSOLE_TX_QUEUE		1
+
+struct con_dev {
+	pthread_mutex_t			mutex;
+
+	struct virtio_trans		vtrans;
+	struct virt_queue		vqs[VIRTIO_CONSOLE_NUM_QUEUES];
+	struct virtio_console_config	config;
+	u32				features;
+
+	struct thread_pool__job		jobs[VIRTIO_CONSOLE_NUM_QUEUES];
+};
+
+static struct con_dev cdev = {
+	.mutex				= PTHREAD_MUTEX_INITIALIZER,
+
+	.config = {
+		.cols			= 80,
+		.rows			= 24,
+		.max_nr_ports		= 1,
+	},
+};
+
+static int compat_id = -1;
+
+/*
+ * Interrupts are injected for hvc0 only.
+ */
+static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *param)
+{
+	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+	struct virt_queue *vq;
+	u16 out, in;
+	u16 head;
+	int len;
+
+	mutex_lock(&cdev.mutex);
+
+	vq = param;
+
+	if (term_readable(CONSOLE_VIRTIO, 0) && virt_queue__available(vq)) {
+		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+		len = term_getc_iov(CONSOLE_VIRTIO, iov, in, 0);
+		virt_queue__set_used_elem(vq, head, len);
+		cdev.vtrans.trans_ops->signal_vq(kvm, &cdev.vtrans, vq - cdev.vqs);
+	}
+
+	mutex_unlock(&cdev.mutex);
+}
+
+void virtio_console__inject_interrupt(struct kvm *kvm)
+{
+	thread_pool__do_job(&cdev.jobs[VIRTIO_CONSOLE_RX_QUEUE]);
+}
+
+static void virtio_console_handle_callback(struct kvm *kvm, void *param)
+{
+	struct iovec iov[VIRTIO_CONSOLE_QUEUE_SIZE];
+	struct virt_queue *vq;
+	u16 out, in;
+	u16 head;
+	u32 len;
+
+	vq = param;
+
+	/*
+	 * The current Linux implementation polls for the buffer
+	 * to be used, rather than waiting for an interrupt.
+	 * So there is no need to inject an interrupt for the tx path.
+	 */
+
+	while (virt_queue__available(vq)) {
+		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+		len = term_putc_iov(CONSOLE_VIRTIO, iov, out, 0);
+		virt_queue__set_used_elem(vq, head, len);
+	}
+
+}
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct con_dev *cdev = dev;
+
+	((u8 *)(&cdev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct con_dev *cdev = dev;
+
+	return ((u8 *)(&cdev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 0;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	/* Unused */
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct virt_queue *queue;
+	void *p;
+
+	BUG_ON(vq >= VIRTIO_CONSOLE_NUM_QUEUES);
+
+	compat__remove_message(compat_id);
+
+	queue			= &cdev.vqs[vq];
+	queue->pfn		= pfn;
+	p			= guest_pfn_to_host(kvm, queue->pfn);
+
+	vring_init(&queue->vring, VIRTIO_CONSOLE_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	if (vq == VIRTIO_CONSOLE_TX_QUEUE)
+		thread_pool__init_job(&cdev.jobs[vq], kvm, virtio_console_handle_callback, queue);
+	else if (vq == VIRTIO_CONSOLE_RX_QUEUE)
+		thread_pool__init_job(&cdev.jobs[vq], kvm, virtio_console__inject_interrupt_callback, queue);
+
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct con_dev *cdev = dev;
+
+	thread_pool__do_job(&cdev->jobs[vq]);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct con_dev *cdev = dev;
+
+	return cdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_CONSOLE_QUEUE_SIZE;
+}
+
+static struct virtio_ops con_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+};
+
+void virtio_console__init(struct kvm *kvm)
+{
+	virtio_trans_init(&cdev.vtrans, VIRTIO_PCI);
+
+	cdev.vtrans.trans_ops->init(kvm, &cdev.vtrans, &cdev, PCI_DEVICE_ID_VIRTIO_CONSOLE,
+					VIRTIO_ID_CONSOLE, PCI_CLASS_CONSOLE);
+	cdev.vtrans.virtio_ops = &con_dev_virtio_ops;
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-console device was not detected",
+						"While you have requested a virtio-console device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_VIRTIO_CONSOLE=y enabled "
+						"in its .config");
+}
diff --git a/tools/kvm/virtio/core.c b/tools/kvm/virtio/core.c
new file mode 100644
index 0000000..c68572c
--- /dev/null
+++ b/tools/kvm/virtio/core.c
@@ -0,0 +1,158 @@
+#include <linux/virtio_ring.h>
+#include <linux/types.h>
+#include <sys/uio.h>
+
+#include "kvm/barrier.h"
+
+#include "kvm/kvm.h"
+#include "kvm/virtio.h"
+
+struct vring_used_elem *virt_queue__set_used_elem(struct virt_queue *queue, u32 head, u32 len)
+{
+	struct vring_used_elem *used_elem;
+
+	used_elem	= &queue->vring.used->ring[queue->vring.used->idx % queue->vring.num];
+	used_elem->id	= head;
+	used_elem->len	= len;
+
+	/*
+	 * Use wmb to assure that used elem was updated with head and len.
+	 * We need a wmb here since we can't advance idx unless we're ready
+	 * to pass the used element to the guest.
+	 */
+	wmb();
+	queue->vring.used->idx++;
+
+	/*
+	 * Use wmb to assure used idx has been increased before we signal the guest.
+	 * Without a wmb here the guest may ignore the queue since it won't see
+	 * an updated idx.
+	 */
+	wmb();
+
+	return used_elem;
+}
+
+/*
+ * Each buffer in the virtqueues is actually a chain of descriptors.  This
+ * function returns the next descriptor in the chain, or vq->vring.num if we're
+ * at the end.
+ */
+static unsigned next_desc(struct vring_desc *desc,
+			  unsigned int i, unsigned int max)
+{
+	unsigned int next;
+
+	/* If this descriptor says it doesn't chain, we're done. */
+	if (!(desc[i].flags & VRING_DESC_F_NEXT))
+		return max;
+
+	/* Check they're not leading us off end of descriptors. */
+	next = desc[i].next;
+	/* Make sure compiler knows to grab that: we don't want it changing! */
+	wmb();
+
+	return next;
+}
+
+u16 virt_queue__get_head_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, u16 head, struct kvm *kvm)
+{
+	struct vring_desc *desc;
+	u16 idx;
+	u16 max;
+
+	idx = head;
+	*out = *in = 0;
+	max = vq->vring.num;
+	desc = vq->vring.desc;
+
+	if (desc[idx].flags & VRING_DESC_F_INDIRECT) {
+		max = desc[idx].len / sizeof(struct vring_desc);
+		desc = guest_flat_to_host(kvm, desc[idx].addr);
+		idx = 0;
+	}
+
+	do {
+		/* Grab the first descriptor, and check it's OK. */
+		iov[*out + *in].iov_len = desc[idx].len;
+		iov[*out + *in].iov_base = guest_flat_to_host(kvm, desc[idx].addr);
+		/* If this is an input descriptor, increment that count. */
+		if (desc[idx].flags & VRING_DESC_F_WRITE)
+			(*in)++;
+		else
+			(*out)++;
+	} while ((idx = next_desc(desc, idx, max)) != max);
+
+	return head;
+}
+
+u16 virt_queue__get_iov(struct virt_queue *vq, struct iovec iov[], u16 *out, u16 *in, struct kvm *kvm)
+{
+	u16 head;
+
+	head = virt_queue__pop(vq);
+
+	return virt_queue__get_head_iov(vq, iov, out, in, head, kvm);
+}
+
+/* in and out are relative to guest */
+u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
+			      struct iovec in_iov[], struct iovec out_iov[],
+			      u16 *in, u16 *out)
+{
+	struct vring_desc *desc;
+	u16 head, idx;
+
+	idx = head = virt_queue__pop(queue);
+	*out = *in = 0;
+	do {
+		desc = virt_queue__get_desc(queue, idx);
+		if (desc->flags & VRING_DESC_F_WRITE) {
+			in_iov[*in].iov_base = guest_flat_to_host(kvm,
+								  desc->addr);
+			in_iov[*in].iov_len = desc->len;
+			(*in)++;
+		} else {
+			out_iov[*out].iov_base = guest_flat_to_host(kvm,
+								    desc->addr);
+			out_iov[*out].iov_len = desc->len;
+			(*out)++;
+		}
+		if (desc->flags & VRING_DESC_F_NEXT)
+			idx = desc->next;
+		else
+			break;
+	} while (1);
+
+	return head;
+}
+
+int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off)
+{
+	if (msix) {
+		if (offset < 4)
+			return VIRTIO_PCI_O_MSIX;
+		else
+			offset -= 4;
+	}
+
+	*config_off = offset;
+
+	return VIRTIO_PCI_O_CONFIG;
+}
+
+bool virtio_queue__should_signal(struct virt_queue *vq)
+{
+	u16 old_idx, new_idx, event_idx;
+
+	old_idx		= vq->last_used_signalled;
+	new_idx		= vq->vring.used->idx;
+	event_idx	= vring_used_event(&vq->vring);
+
+	if (vring_need_event(event_idx, new_idx, old_idx)) {
+		vq->last_used_signalled = new_idx;
+		return true;
+	}
+
+	return false;
+}
diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c
new file mode 100644
index 0000000..5e29708
--- /dev/null
+++ b/tools/kvm/virtio/net.c
@@ -0,0 +1,547 @@
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/virtio-net.h"
+#include "kvm/virtio.h"
+#include "kvm/types.h"
+#include "kvm/mutex.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/irq.h"
+#include "kvm/uip.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/if_tun.h>
+#include <linux/types.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/eventfd.h>
+
+#define VIRTIO_NET_QUEUE_SIZE		128
+#define VIRTIO_NET_NUM_QUEUES		2
+#define VIRTIO_NET_RX_QUEUE		0
+#define VIRTIO_NET_TX_QUEUE		1
+
+struct net_dev;
+
+extern struct kvm *kvm;
+
+struct net_dev_operations {
+	int (*rx)(struct iovec *iov, u16 in, struct net_dev *ndev);
+	int (*tx)(struct iovec *iov, u16 in, struct net_dev *ndev);
+};
+
+struct net_dev {
+	pthread_mutex_t			mutex;
+	struct virtio_trans		vtrans;
+	struct list_head		list;
+
+	struct virt_queue		vqs[VIRTIO_NET_NUM_QUEUES];
+	struct virtio_net_config	config;
+	u32				features;
+
+	pthread_t			io_rx_thread;
+	pthread_mutex_t			io_rx_lock;
+	pthread_cond_t			io_rx_cond;
+
+	pthread_t			io_tx_thread;
+	pthread_mutex_t			io_tx_lock;
+	pthread_cond_t			io_tx_cond;
+
+	int				vhost_fd;
+	int				tap_fd;
+	char				tap_name[IFNAMSIZ];
+
+	int				mode;
+
+	struct uip_info			info;
+	struct net_dev_operations	*ops;
+	struct kvm			*kvm;
+};
+
+static LIST_HEAD(ndevs);
+static int compat_id = -1;
+
+static void *virtio_net_rx_thread(void *p)
+{
+	struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
+	struct virt_queue *vq;
+	struct kvm *kvm;
+	struct net_dev *ndev = p;
+	u16 out, in;
+	u16 head;
+	int len;
+
+	kvm	= ndev->kvm;
+	vq	= &ndev->vqs[VIRTIO_NET_RX_QUEUE];
+
+	while (1) {
+		mutex_lock(&ndev->io_rx_lock);
+		if (!virt_queue__available(vq))
+			pthread_cond_wait(&ndev->io_rx_cond, &ndev->io_rx_lock);
+		mutex_unlock(&ndev->io_rx_lock);
+
+		while (virt_queue__available(vq)) {
+			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+			len = ndev->ops->rx(iov, in, ndev);
+			virt_queue__set_used_elem(vq, head, len);
+
+			/* We should interrupt guest right now, otherwise latency is huge. */
+			if (virtio_queue__should_signal(&ndev->vqs[VIRTIO_NET_RX_QUEUE]))
+				ndev->vtrans.trans_ops->signal_vq(kvm, &ndev->vtrans,
+								VIRTIO_NET_RX_QUEUE);
+		}
+	}
+
+	pthread_exit(NULL);
+	return NULL;
+
+}
+
+static void *virtio_net_tx_thread(void *p)
+{
+	struct iovec iov[VIRTIO_NET_QUEUE_SIZE];
+	struct virt_queue *vq;
+	struct kvm *kvm;
+	struct net_dev *ndev = p;
+	u16 out, in;
+	u16 head;
+	int len;
+
+	kvm	= ndev->kvm;
+	vq	= &ndev->vqs[VIRTIO_NET_TX_QUEUE];
+
+	while (1) {
+		mutex_lock(&ndev->io_tx_lock);
+		if (!virt_queue__available(vq))
+			pthread_cond_wait(&ndev->io_tx_cond, &ndev->io_tx_lock);
+		mutex_unlock(&ndev->io_tx_lock);
+
+		while (virt_queue__available(vq)) {
+			head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
+			len = ndev->ops->tx(iov, out, ndev);
+			virt_queue__set_used_elem(vq, head, len);
+		}
+
+		if (virtio_queue__should_signal(&ndev->vqs[VIRTIO_NET_TX_QUEUE]))
+			ndev->vtrans.trans_ops->signal_vq(kvm, &ndev->vtrans, VIRTIO_NET_TX_QUEUE);
+	}
+
+	pthread_exit(NULL);
+
+	return NULL;
+
+}
+
+static void virtio_net_handle_callback(struct kvm *kvm, struct net_dev *ndev, int queue)
+{
+	switch (queue) {
+	case VIRTIO_NET_TX_QUEUE:
+		mutex_lock(&ndev->io_tx_lock);
+		pthread_cond_signal(&ndev->io_tx_cond);
+		mutex_unlock(&ndev->io_tx_lock);
+		break;
+	case VIRTIO_NET_RX_QUEUE:
+		mutex_lock(&ndev->io_rx_lock);
+		pthread_cond_signal(&ndev->io_rx_cond);
+		mutex_unlock(&ndev->io_rx_lock);
+		break;
+	default:
+		pr_warning("Unknown queue index %u", queue);
+	}
+}
+
+static bool virtio_net__tap_init(const struct virtio_net_params *params,
+					struct net_dev *ndev)
+{
+	int sock = socket(AF_INET, SOCK_STREAM, 0);
+	int pid, status, offload, hdr_len;
+	struct sockaddr_in sin = {0};
+	struct ifreq ifr;
+
+	/* Did the user already gave us the FD? */
+	if (params->fd) {
+		ndev->tap_fd = params->fd;
+		return 1;
+	}
+
+	ndev->tap_fd = open("/dev/net/tun", O_RDWR);
+	if (ndev->tap_fd < 0) {
+		pr_warning("Unable to open /dev/net/tun");
+		goto fail;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+	if (ioctl(ndev->tap_fd, TUNSETIFF, &ifr) < 0) {
+		pr_warning("Config tap device error. Are you root?");
+		goto fail;
+	}
+
+	strncpy(ndev->tap_name, ifr.ifr_name, sizeof(ndev->tap_name));
+
+	if (ioctl(ndev->tap_fd, TUNSETNOCSUM, 1) < 0) {
+		pr_warning("Config tap device TUNSETNOCSUM error");
+		goto fail;
+	}
+
+	hdr_len = sizeof(struct virtio_net_hdr);
+	if (ioctl(ndev->tap_fd, TUNSETVNETHDRSZ, &hdr_len) < 0)
+		pr_warning("Config tap device TUNSETVNETHDRSZ error");
+
+	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO;
+	if (ioctl(ndev->tap_fd, TUNSETOFFLOAD, offload) < 0) {
+		pr_warning("Config tap device TUNSETOFFLOAD error");
+		goto fail;
+	}
+
+	if (strcmp(params->script, "none")) {
+		pid = fork();
+		if (pid == 0) {
+			execl(params->script, params->script, ndev->tap_name, NULL);
+			_exit(1);
+		} else {
+			waitpid(pid, &status, 0);
+			if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
+				pr_warning("Fail to setup tap by %s", params->script);
+				goto fail;
+			}
+		}
+	} else {
+		memset(&ifr, 0, sizeof(ifr));
+		strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name));
+		sin.sin_addr.s_addr = inet_addr(params->host_ip);
+		memcpy(&(ifr.ifr_addr), &sin, sizeof(ifr.ifr_addr));
+		ifr.ifr_addr.sa_family = AF_INET;
+		if (ioctl(sock, SIOCSIFADDR, &ifr) < 0) {
+			pr_warning("Could not set ip address on tap device");
+			goto fail;
+		}
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ndev->tap_name, sizeof(ndev->tap_name));
+	ioctl(sock, SIOCGIFFLAGS, &ifr);
+	ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
+	if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0)
+		pr_warning("Could not bring tap device up");
+
+	close(sock);
+
+	return 1;
+
+fail:
+	if (sock >= 0)
+		close(sock);
+	if (ndev->tap_fd >= 0)
+		close(ndev->tap_fd);
+
+	return 0;
+}
+
+static void virtio_net__io_thread_init(struct kvm *kvm, struct net_dev *ndev)
+{
+	pthread_mutex_init(&ndev->io_tx_lock, NULL);
+	pthread_mutex_init(&ndev->io_rx_lock, NULL);
+
+	pthread_cond_init(&ndev->io_tx_cond, NULL);
+	pthread_cond_init(&ndev->io_rx_cond, NULL);
+
+	pthread_create(&ndev->io_tx_thread, NULL, virtio_net_tx_thread, ndev);
+	pthread_create(&ndev->io_rx_thread, NULL, virtio_net_rx_thread, ndev);
+}
+
+static inline int tap_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
+{
+	return writev(ndev->tap_fd, iov, out);
+}
+
+static inline int tap_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
+{
+	return readv(ndev->tap_fd, iov, in);
+}
+
+static inline int uip_ops_tx(struct iovec *iov, u16 out, struct net_dev *ndev)
+{
+	return uip_tx(iov, out, &ndev->info);
+}
+
+static inline int uip_ops_rx(struct iovec *iov, u16 in, struct net_dev *ndev)
+{
+	return uip_rx(iov, in, &ndev->info);
+}
+
+static struct net_dev_operations tap_ops = {
+	.rx	= tap_ops_rx,
+	.tx	= tap_ops_tx,
+};
+
+static struct net_dev_operations uip_ops = {
+	.rx	= uip_ops_rx,
+	.tx	= uip_ops_tx,
+};
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	struct net_dev *ndev = dev;
+
+	((u8 *)(&ndev->config))[offset] = data;
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	struct net_dev *ndev = dev;
+
+	return ((u8 *)(&ndev->config))[offset];
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	return 1UL << VIRTIO_NET_F_MAC
+		| 1UL << VIRTIO_NET_F_CSUM
+		| 1UL << VIRTIO_NET_F_HOST_UFO
+		| 1UL << VIRTIO_NET_F_HOST_TSO4
+		| 1UL << VIRTIO_NET_F_HOST_TSO6
+		| 1UL << VIRTIO_NET_F_GUEST_UFO
+		| 1UL << VIRTIO_NET_F_GUEST_TSO4
+		| 1UL << VIRTIO_NET_F_GUEST_TSO6
+		| 1UL << VIRTIO_RING_F_EVENT_IDX
+		| 1UL << VIRTIO_RING_F_INDIRECT_DESC;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	struct net_dev *ndev = dev;
+
+	ndev->features = features;
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct vhost_vring_state state = { .index = vq };
+	struct vhost_vring_addr addr;
+	struct net_dev *ndev = dev;
+	struct virt_queue *queue;
+	void *p;
+	int r;
+
+	compat__remove_message(compat_id);
+
+	queue		= &ndev->vqs[vq];
+	queue->pfn	= pfn;
+	p		= guest_pfn_to_host(kvm, queue->pfn);
+
+	vring_init(&queue->vring, VIRTIO_NET_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	if (ndev->vhost_fd == 0)
+		return 0;
+
+	state.num = queue->vring.num;
+	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_NUM, &state);
+	if (r < 0)
+		die_perror("VHOST_SET_VRING_NUM failed");
+	state.num = 0;
+	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_BASE, &state);
+	if (r < 0)
+		die_perror("VHOST_SET_VRING_BASE failed");
+
+	addr = (struct vhost_vring_addr) {
+		.index = vq,
+		.desc_user_addr = (u64)(unsigned long)queue->vring.desc,
+		.avail_user_addr = (u64)(unsigned long)queue->vring.avail,
+		.used_user_addr = (u64)(unsigned long)queue->vring.used,
+	};
+
+	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_ADDR, &addr);
+	if (r < 0)
+		die_perror("VHOST_SET_VRING_ADDR failed");
+
+	return 0;
+}
+
+static void notify_vq_gsi(struct kvm *kvm, void *dev, u32 vq, u32 gsi)
+{
+	struct net_dev *ndev = dev;
+	struct kvm_irqfd irq;
+	struct vhost_vring_file file;
+	int r;
+
+	if (ndev->vhost_fd == 0)
+		return;
+
+	irq = (struct kvm_irqfd) {
+		.gsi	= gsi,
+		.fd	= eventfd(0, 0),
+	};
+	file = (struct vhost_vring_file) {
+		.index	= vq,
+		.fd	= irq.fd,
+	};
+
+	r = ioctl(kvm->vm_fd, KVM_IRQFD, &irq);
+	if (r < 0)
+		die_perror("KVM_IRQFD failed");
+
+	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_CALL, &file);
+	if (r < 0)
+		die_perror("VHOST_SET_VRING_CALL failed");
+	file.fd = ndev->tap_fd;
+	r = ioctl(ndev->vhost_fd, VHOST_NET_SET_BACKEND, &file);
+	if (r != 0)
+		die("VHOST_NET_SET_BACKEND failed %d", errno);
+
+}
+
+static void notify_vq_eventfd(struct kvm *kvm, void *dev, u32 vq, u32 efd)
+{
+	struct net_dev *ndev = dev;
+	struct vhost_vring_file file = {
+		.index	= vq,
+		.fd	= efd,
+	};
+	int r;
+
+	if (ndev->vhost_fd == 0)
+		return;
+
+	r = ioctl(ndev->vhost_fd, VHOST_SET_VRING_KICK, &file);
+	if (r < 0)
+		die_perror("VHOST_SET_VRING_KICK failed");
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct net_dev *ndev = dev;
+
+	virtio_net_handle_callback(kvm, ndev, vq);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct net_dev *ndev = dev;
+
+	return ndev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_NET_QUEUE_SIZE;
+}
+
+static struct virtio_ops net_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+	.notify_vq_gsi		= notify_vq_gsi,
+	.notify_vq_eventfd	= notify_vq_eventfd,
+};
+
+static void virtio_net__vhost_init(struct kvm *kvm, struct net_dev *ndev)
+{
+	u64 features = 1UL << VIRTIO_RING_F_EVENT_IDX;
+	struct vhost_memory *mem;
+	int r;
+
+	ndev->vhost_fd = open("/dev/vhost-net", O_RDWR);
+	if (ndev->vhost_fd < 0)
+		die_perror("Failed openning vhost-net device");
+
+	mem = malloc(sizeof(*mem) + sizeof(struct vhost_memory_region));
+	if (mem == NULL)
+		die("Failed allocating memory for vhost memory map");
+
+	mem->nregions = 1;
+	mem->regions[0] = (struct vhost_memory_region) {
+		.guest_phys_addr	= 0,
+		.memory_size		= kvm->ram_size,
+		.userspace_addr		= (unsigned long)kvm->ram_start,
+	};
+
+	r = ioctl(ndev->vhost_fd, VHOST_SET_OWNER);
+	if (r != 0)
+		die_perror("VHOST_SET_OWNER failed");
+
+	r = ioctl(ndev->vhost_fd, VHOST_SET_FEATURES, &features);
+	if (r != 0)
+		die_perror("VHOST_SET_FEATURES failed");
+	r = ioctl(ndev->vhost_fd, VHOST_SET_MEM_TABLE, mem);
+	if (r != 0)
+		die_perror("VHOST_SET_MEM_TABLE failed");
+	free(mem);
+}
+
+void virtio_net__init(const struct virtio_net_params *params)
+{
+	int i;
+	struct net_dev *ndev;
+
+	if (!params)
+		return;
+
+	ndev = calloc(1, sizeof(struct net_dev));
+	if (ndev == NULL)
+		die("Failed allocating ndev");
+
+	list_add_tail(&ndev->list, &ndevs);
+
+	ndev->kvm = params->kvm;
+
+	mutex_init(&ndev->mutex);
+	ndev->config.status = VIRTIO_NET_S_LINK_UP;
+
+	for (i = 0 ; i < 6 ; i++) {
+		ndev->config.mac[i]		= params->guest_mac[i];
+		ndev->info.guest_mac.addr[i]	= params->guest_mac[i];
+		ndev->info.host_mac.addr[i]	= params->host_mac[i];
+	}
+
+	ndev->mode = params->mode;
+	if (ndev->mode == NET_MODE_TAP) {
+		if (!virtio_net__tap_init(params, ndev))
+			die_perror("You have requested a TAP device, but creation of one has"
+					"failed because:");
+		ndev->ops = &tap_ops;
+	} else {
+		ndev->info.host_ip		= ntohl(inet_addr(params->host_ip));
+		ndev->info.guest_ip		= ntohl(inet_addr(params->guest_ip));
+		ndev->info.guest_netmask	= ntohl(inet_addr("255.255.255.0"));
+		ndev->info.buf_nr		= 20,
+		uip_init(&ndev->info);
+		ndev->ops = &uip_ops;
+	}
+
+	virtio_trans_init(&ndev->vtrans, VIRTIO_PCI);
+	ndev->vtrans.trans_ops->init(kvm, &ndev->vtrans, ndev, PCI_DEVICE_ID_VIRTIO_NET,
+					VIRTIO_ID_NET, PCI_CLASS_NET);
+	ndev->vtrans.virtio_ops = &net_dev_virtio_ops;
+
+	if (params->vhost)
+		virtio_net__vhost_init(params->kvm, ndev);
+	else
+		virtio_net__io_thread_init(params->kvm, ndev);
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-net device was not detected",
+						"While you have requested a virtio-net device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_VIRTIO_NET=y enabled "
+						"in its .config");
+}
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
new file mode 100644
index 0000000..3051314
--- /dev/null
+++ b/tools/kvm/virtio/pci.c
@@ -0,0 +1,346 @@
+#include "kvm/virtio-pci.h"
+
+#include "kvm/ioport.h"
+#include "kvm/kvm.h"
+#include "kvm/virtio-pci-dev.h"
+#include "kvm/irq.h"
+#include "kvm/virtio.h"
+#include "kvm/ioeventfd.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/virtio_pci.h>
+#include <linux/byteorder.h>
+#include <string.h>
+
+struct virtio_trans_ops *virtio_pci__get_trans_ops(void)
+{
+	static struct virtio_trans_ops virtio_pci_trans = (struct virtio_trans_ops) {
+		.signal_vq	= virtio_pci__signal_vq,
+		.signal_config	= virtio_pci__signal_config,
+		.init		= virtio_pci__init,
+	};
+	return &virtio_pci_trans;
+};
+
+static void virtio_pci__ioevent_callback(struct kvm *kvm, void *param)
+{
+	struct virtio_pci_ioevent_param *ioeventfd = param;
+	struct virtio_pci *vpci = ioeventfd->vtrans->virtio;
+
+	ioeventfd->vtrans->virtio_ops->notify_vq(kvm, vpci->dev, ioeventfd->vq);
+}
+
+static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
+{
+	struct ioevent ioevent;
+	struct virtio_pci *vpci = vtrans->virtio;
+
+	vpci->ioeventfds[vq] = (struct virtio_pci_ioevent_param) {
+		.vtrans		= vtrans,
+		.vq		= vq,
+	};
+
+	ioevent = (struct ioevent) {
+		.io_addr	= vpci->base_addr + VIRTIO_PCI_QUEUE_NOTIFY,
+		.io_len		= sizeof(u16),
+		.fn		= virtio_pci__ioevent_callback,
+		.fn_ptr		= &vpci->ioeventfds[vq],
+		.datamatch	= vq,
+		.fn_kvm		= kvm,
+		.fd		= eventfd(0, 0),
+	};
+
+	ioeventfd__add_event(&ioevent);
+
+	if (vtrans->virtio_ops->notify_vq_eventfd)
+		vtrans->virtio_ops->notify_vq_eventfd(kvm, vpci->dev, vq, ioevent.fd);
+
+	return 0;
+}
+
+static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
+{
+	return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
+}
+
+static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
+					void *data, int size, int offset)
+{
+	u32 config_offset;
+	struct virtio_pci *vpci = vtrans->virtio;
+	int type = virtio__get_dev_specific_field(offset - 20,
+							virtio_pci__msix_enabled(vpci),
+							&config_offset);
+	if (type == VIRTIO_PCI_O_MSIX) {
+		switch (offset) {
+		case VIRTIO_MSI_CONFIG_VECTOR:
+			ioport__write16(data, vpci->config_vector);
+			break;
+		case VIRTIO_MSI_QUEUE_VECTOR:
+			ioport__write16(data, vpci->vq_vector[vpci->queue_selector]);
+			break;
+		};
+
+		return true;
+	} else if (type == VIRTIO_PCI_O_CONFIG) {
+		u8 cfg;
+
+		cfg = vtrans->virtio_ops->get_config(kvm, vpci->dev, config_offset);
+		ioport__write8(data, cfg);
+		return true;
+	}
+
+	return false;
+}
+
+static bool virtio_pci__io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	unsigned long offset;
+	bool ret = true;
+	struct virtio_trans *vtrans;
+	struct virtio_pci *vpci;
+	u32 val;
+
+	vtrans = ioport->priv;
+	vpci = vtrans->virtio;
+	offset = port - vpci->base_addr;
+
+	switch (offset) {
+	case VIRTIO_PCI_HOST_FEATURES:
+		val = vtrans->virtio_ops->get_host_features(kvm, vpci->dev);
+		ioport__write32(data, val);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN:
+		val = vtrans->virtio_ops->get_pfn_vq(kvm, vpci->dev, vpci->queue_selector);
+		ioport__write32(data, val);
+		break;
+	case VIRTIO_PCI_QUEUE_NUM:
+		val = vtrans->virtio_ops->get_size_vq(kvm, vpci->dev, vpci->queue_selector);
+		ioport__write16(data, val);
+		break;
+	case VIRTIO_PCI_STATUS:
+		ioport__write8(data, vpci->status);
+		break;
+	case VIRTIO_PCI_ISR:
+		ioport__write8(data, vpci->isr);
+		kvm__irq_line(kvm, vpci->pci_hdr.irq_line, VIRTIO_IRQ_LOW);
+		vpci->isr = VIRTIO_IRQ_LOW;
+		break;
+	default:
+		ret = virtio_pci__specific_io_in(kvm, vtrans, port, data, size, offset);
+		break;
+	};
+
+	return ret;
+}
+
+static bool virtio_pci__specific_io_out(struct kvm *kvm, struct virtio_trans *vtrans, u16 port,
+					void *data, int size, int offset)
+{
+	struct virtio_pci *vpci = vtrans->virtio;
+	u32 config_offset, gsi, vec;
+	int type = virtio__get_dev_specific_field(offset - 20, virtio_pci__msix_enabled(vpci),
+							&config_offset);
+	if (type == VIRTIO_PCI_O_MSIX) {
+		switch (offset) {
+		case VIRTIO_MSI_CONFIG_VECTOR:
+			vec = vpci->config_vector = ioport__read16(data);
+
+			gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
+
+			vpci->config_gsi = gsi;
+			break;
+		case VIRTIO_MSI_QUEUE_VECTOR:
+			vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
+
+			gsi = irq__add_msix_route(kvm, &vpci->msix_table[vec].msg);
+			vpci->gsis[vpci->queue_selector] = gsi;
+			if (vtrans->virtio_ops->notify_vq_gsi)
+				vtrans->virtio_ops->notify_vq_gsi(kvm, vpci->dev,
+							vpci->queue_selector, gsi);
+			break;
+		};
+
+		return true;
+	} else if (type == VIRTIO_PCI_O_CONFIG) {
+		vtrans->virtio_ops->set_config(kvm, vpci->dev, *(u8 *)data, config_offset);
+
+		return true;
+	}
+
+	return false;
+}
+
+static bool virtio_pci__io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	unsigned long offset;
+	bool ret = true;
+	struct virtio_trans *vtrans;
+	struct virtio_pci *vpci;
+	u32 val;
+
+	vtrans = ioport->priv;
+	vpci = vtrans->virtio;
+	offset = port - vpci->base_addr;
+
+	switch (offset) {
+	case VIRTIO_PCI_GUEST_FEATURES:
+		val = ioport__read32(data);
+		vtrans->virtio_ops->set_guest_features(kvm, vpci->dev, val);
+		break;
+	case VIRTIO_PCI_QUEUE_PFN:
+		val = ioport__read32(data);
+		virtio_pci__init_ioeventfd(kvm, vtrans, vpci->queue_selector);
+		vtrans->virtio_ops->init_vq(kvm, vpci->dev, vpci->queue_selector, val);
+		break;
+	case VIRTIO_PCI_QUEUE_SEL:
+		vpci->queue_selector = ioport__read16(data);
+		break;
+	case VIRTIO_PCI_QUEUE_NOTIFY:
+		val = ioport__read16(data);
+		vtrans->virtio_ops->notify_vq(kvm, vpci->dev, val);
+		break;
+	case VIRTIO_PCI_STATUS:
+		vpci->status = ioport__read8(data);
+		break;
+	default:
+		ret = virtio_pci__specific_io_out(kvm, vtrans, port, data, size, offset);
+		break;
+	};
+
+	return ret;
+}
+
+static struct ioport_operations virtio_pci__io_ops = {
+	.io_in	= virtio_pci__io_in,
+	.io_out	= virtio_pci__io_out,
+};
+
+static void callback_mmio_table(u64 addr, u8 *data, u32 len, u8 is_write, void *ptr)
+{
+	struct virtio_pci *vpci = ptr;
+	void *table;
+	u32 offset;
+
+	if (addr > vpci->msix_io_block + PCI_IO_SIZE) {
+		table	= &vpci->msix_pba;
+		offset	= vpci->msix_io_block + PCI_IO_SIZE;
+	} else {
+		table	= &vpci->msix_table;
+		offset	= vpci->msix_io_block;
+	}
+
+	if (is_write)
+		memcpy(table + addr - offset, data, len);
+	else
+		memcpy(data, table + addr - offset, len);
+}
+
+int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_trans *vtrans, u32 vq)
+{
+	struct virtio_pci *vpci = vtrans->virtio;
+	int tbl = vpci->vq_vector[vq];
+
+	if (virtio_pci__msix_enabled(vpci)) {
+		if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+		    vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+
+			vpci->msix_pba |= 1 << tbl;
+			return 0;
+		}
+
+		kvm__irq_trigger(kvm, vpci->gsis[vq]);
+	} else {
+		vpci->isr = VIRTIO_IRQ_HIGH;
+		kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
+	}
+	return 0;
+}
+
+int virtio_pci__signal_config(struct kvm *kvm, struct virtio_trans *vtrans)
+{
+	struct virtio_pci *vpci = vtrans->virtio;
+	int tbl = vpci->config_vector;
+
+	if (virtio_pci__msix_enabled(vpci)) {
+		if (vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+		    vpci->msix_table[tbl].ctrl & cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
+
+			vpci->msix_pba |= 1 << tbl;
+			return 0;
+		}
+
+		kvm__irq_trigger(kvm, vpci->config_gsi);
+	} else {
+		vpci->isr = VIRTIO_PCI_ISR_CONFIG;
+		kvm__irq_trigger(kvm, vpci->pci_hdr.irq_line);
+	}
+
+	return 0;
+}
+
+int virtio_pci__init(struct kvm *kvm, struct virtio_trans *vtrans, void *dev,
+			int device_id, int subsys_id, int class)
+{
+	struct virtio_pci *vpci = vtrans->virtio;
+	u8 pin, line, ndev;
+
+	vpci->dev = dev;
+	vpci->msix_io_block = pci_get_io_space_block(PCI_IO_SIZE * 2);
+
+	vpci->base_addr = ioport__register(IOPORT_EMPTY, &virtio_pci__io_ops, IOPORT_SIZE, vtrans);
+	kvm__register_mmio(kvm, vpci->msix_io_block, PCI_IO_SIZE, false, callback_mmio_table, vpci);
+
+	vpci->pci_hdr = (struct pci_device_header) {
+		.vendor_id		= cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+		.device_id		= cpu_to_le16(device_id),
+		.header_type		= PCI_HEADER_TYPE_NORMAL,
+		.revision_id		= 0,
+		.class[0]		= class & 0xff,
+		.class[1]		= (class >> 8) & 0xff,
+		.class[2]		= (class >> 16) & 0xff,
+		.subsys_vendor_id	= cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+		.subsys_id		= cpu_to_le16(subsys_id),
+		.bar[0]			= cpu_to_le32(vpci->base_addr
+							| PCI_BASE_ADDRESS_SPACE_IO),
+		.bar[1]			= cpu_to_le32(vpci->msix_io_block
+							| PCI_BASE_ADDRESS_SPACE_MEMORY),
+		.status			= cpu_to_le16(PCI_STATUS_CAP_LIST),
+		.capabilities		= (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
+		.bar_size[0]		= IOPORT_SIZE,
+		.bar_size[1]		= PCI_IO_SIZE,
+		.bar_size[3]		= PCI_IO_SIZE,
+	};
+
+	vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
+	vpci->pci_hdr.msix.next = 0;
+	/*
+	 * We at most have VIRTIO_PCI_MAX_VQ entries for virt queue,
+	 * VIRTIO_PCI_MAX_CONFIG entries for config.
+	 *
+	 * To quote the PCI spec:
+	 *
+	 * System software reads this field to determine the
+	 * MSI-X Table Size N, which is encoded as N-1.
+	 * For example, a returned value of "00000000011"
+	 * indicates a table size of 4.
+	 */
+	vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 1);
+
+	/*
+	 * Both table and PBA could be mapped on the same BAR, but for now
+	 * we're not in short of BARs
+	 */
+	vpci->pci_hdr.msix.table_offset = cpu_to_le32(1); /* Use BAR 1 */
+	vpci->pci_hdr.msix.pba_offset = cpu_to_le32(1 | PCI_IO_SIZE); /* Use BAR 3 */
+	vpci->config_vector = 0;
+
+	if (irq__register_device(subsys_id, &ndev, &pin, &line) < 0)
+		return -1;
+
+	vpci->pci_hdr.irq_pin	= pin;
+	vpci->pci_hdr.irq_line	= line;
+	pci__register(&vpci->pci_hdr, ndev);
+
+	return 0;
+}
diff --git a/tools/kvm/virtio/rng.c b/tools/kvm/virtio/rng.c
new file mode 100644
index 0000000..c9430cb
--- /dev/null
+++ b/tools/kvm/virtio/rng.c
@@ -0,0 +1,188 @@
+#include "kvm/virtio-rng.h"
+
+#include "kvm/virtio-pci-dev.h"
+
+#include "kvm/virtio.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+#include "kvm/threadpool.h"
+#include "kvm/guest_compat.h"
+#include "kvm/virtio-trans.h"
+
+#include <linux/virtio_ring.h>
+#include <linux/virtio_rng.h>
+
+#include <linux/list.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pthread.h>
+#include <linux/kernel.h>
+
+#define NUM_VIRT_QUEUES		1
+#define VIRTIO_RNG_QUEUE_SIZE	128
+
+struct rng_dev_job {
+	struct virt_queue	*vq;
+	struct rng_dev		*rdev;
+	struct thread_pool__job	job_id;
+};
+
+struct rng_dev {
+	struct list_head	list;
+	struct virtio_trans	vtrans;
+
+	int			fd;
+
+	/* virtio queue */
+	struct virt_queue	vqs[NUM_VIRT_QUEUES];
+	struct rng_dev_job	jobs[NUM_VIRT_QUEUES];
+};
+
+static LIST_HEAD(rdevs);
+static int compat_id = -1;
+
+static void set_config(struct kvm *kvm, void *dev, u8 data, u32 offset)
+{
+	/* Unused */
+}
+
+static u8 get_config(struct kvm *kvm, void *dev, u32 offset)
+{
+	/* Unused */
+	return 0;
+}
+
+static u32 get_host_features(struct kvm *kvm, void *dev)
+{
+	/* Unused */
+	return 0;
+}
+
+static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
+{
+	/* Unused */
+}
+
+static bool virtio_rng_do_io_request(struct kvm *kvm, struct rng_dev *rdev, struct virt_queue *queue)
+{
+	struct iovec iov[VIRTIO_RNG_QUEUE_SIZE];
+	unsigned int len = 0;
+	u16 out, in, head;
+
+	head	= virt_queue__get_iov(queue, iov, &out, &in, kvm);
+	len	= readv(rdev->fd, iov, in);
+
+	virt_queue__set_used_elem(queue, head, len);
+
+	return true;
+}
+
+static void virtio_rng_do_io(struct kvm *kvm, void *param)
+{
+	struct rng_dev_job *job	= param;
+	struct virt_queue *vq	= job->vq;
+	struct rng_dev *rdev	= job->rdev;
+
+	while (virt_queue__available(vq))
+		virtio_rng_do_io_request(kvm, rdev, vq);
+
+	rdev->vtrans.trans_ops->signal_vq(kvm, &rdev->vtrans, vq - rdev->vqs);
+}
+
+static int init_vq(struct kvm *kvm, void *dev, u32 vq, u32 pfn)
+{
+	struct rng_dev *rdev = dev;
+	struct virt_queue *queue;
+	struct rng_dev_job *job;
+	void *p;
+
+	compat__remove_message(compat_id);
+
+	queue		= &rdev->vqs[vq];
+	queue->pfn	= pfn;
+	p		= guest_pfn_to_host(kvm, queue->pfn);
+
+	job = &rdev->jobs[vq];
+
+	vring_init(&queue->vring, VIRTIO_RNG_QUEUE_SIZE, p, VIRTIO_PCI_VRING_ALIGN);
+
+	*job = (struct rng_dev_job) {
+		.vq	= queue,
+		.rdev	= rdev,
+	};
+
+	thread_pool__init_job(&job->job_id, kvm, virtio_rng_do_io, job);
+
+	return 0;
+}
+
+static int notify_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct rng_dev *rdev = dev;
+
+	thread_pool__do_job(&rdev->jobs[vq].job_id);
+
+	return 0;
+}
+
+static int get_pfn_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	struct rng_dev *rdev = dev;
+
+	return rdev->vqs[vq].pfn;
+}
+
+static int get_size_vq(struct kvm *kvm, void *dev, u32 vq)
+{
+	return VIRTIO_RNG_QUEUE_SIZE;
+}
+
+static struct virtio_ops rng_dev_virtio_ops = (struct virtio_ops) {
+	.set_config		= set_config,
+	.get_config		= get_config,
+	.get_host_features	= get_host_features,
+	.set_guest_features	= set_guest_features,
+	.init_vq		= init_vq,
+	.notify_vq		= notify_vq,
+	.get_pfn_vq		= get_pfn_vq,
+	.get_size_vq		= get_size_vq,
+};
+
+void virtio_rng__init(struct kvm *kvm)
+{
+	struct rng_dev *rdev;
+
+	rdev = malloc(sizeof(*rdev));
+	if (rdev == NULL)
+		return;
+
+	rdev->fd = open("/dev/urandom", O_RDONLY);
+	if (rdev->fd < 0)
+		die("Failed initializing RNG");
+
+	virtio_trans_init(&rdev->vtrans, VIRTIO_PCI);
+	rdev->vtrans.trans_ops->init(kvm, &rdev->vtrans, rdev, PCI_DEVICE_ID_VIRTIO_RNG,
+					VIRTIO_ID_RNG, PCI_CLASS_RNG);
+	rdev->vtrans.virtio_ops = &rng_dev_virtio_ops;
+
+	list_add_tail(&rdev->list, &rdevs);
+
+	if (compat_id != -1)
+		compat_id = compat__add_message("virtio-rng device was not detected",
+						"While you have requested a virtio-rng device, "
+						"the guest kernel did not initialize it.\n"
+						"Please make sure that the guest kernel was "
+						"compiled with CONFIG_HW_RANDOM_VIRTIO=y enabled "
+						"in its .config");
+}
+
+void virtio_rng__delete_all(struct kvm *kvm)
+{
+	struct rng_dev *rdev, *tmp;
+
+	list_for_each_entry_safe(rdev, tmp, &rdevs, list) {
+		list_del(&rdev->list);
+		free(rdev);
+	}
+}
diff --git a/tools/kvm/virtio/trans.c b/tools/kvm/virtio/trans.c
new file mode 100644
index 0000000..50c206d
--- /dev/null
+++ b/tools/kvm/virtio/trans.c
@@ -0,0 +1,22 @@
+#include "kvm/virtio-trans.h"
+
+#include "kvm/virtio-pci.h"
+#include "kvm/util.h"
+
+#include <stdlib.h>
+
+int virtio_trans_init(struct virtio_trans *vtrans, enum virtio_trans_type type)
+{
+	void *trans;
+
+	switch (type) {
+	case VIRTIO_PCI:
+		trans = calloc(sizeof(struct virtio_pci), 1);
+		if (!trans)
+			die("Failed allocating virtio transport");
+		vtrans->virtio = trans;
+		vtrans->trans_ops = virtio_pci__get_trans_ops();
+	default:
+		return -1;
+	};
+}
\ No newline at end of file
diff --git a/tools/kvm/x86/bios.c b/tools/kvm/x86/bios.c
new file mode 100644
index 0000000..0f1bd85
--- /dev/null
+++ b/tools/kvm/x86/bios.c
@@ -0,0 +1,174 @@
+#include "kvm/kvm.h"
+#include "kvm/boot-protocol.h"
+#include "kvm/e820.h"
+#include "kvm/interrupt.h"
+#include "kvm/util.h"
+
+#include <string.h>
+#include <asm/e820.h>
+
+#include "bios/bios-rom.h"
+
+struct irq_handler {
+	unsigned long		address;
+	unsigned int		irq;
+	void			*handler;
+	size_t			size;
+};
+
+#define BIOS_IRQ_PA_ADDR(name)	(MB_BIOS_BEGIN + BIOS_OFFSET__##name)
+#define BIOS_IRQ_FUNC(name)	((char *)&bios_rom[BIOS_OFFSET__##name])
+#define BIOS_IRQ_SIZE(name)	(BIOS_ENTRY_SIZE(BIOS_OFFSET__##name))
+
+#define DEFINE_BIOS_IRQ_HANDLER(_irq, _handler)			\
+	{							\
+		.irq		= _irq,				\
+		.address	= BIOS_IRQ_PA_ADDR(_handler),	\
+		.handler	= BIOS_IRQ_FUNC(_handler),	\
+		.size		= BIOS_IRQ_SIZE(_handler),	\
+	}
+
+static struct irq_handler bios_irq_handlers[] = {
+	DEFINE_BIOS_IRQ_HANDLER(0x10, bios_int10),
+	DEFINE_BIOS_IRQ_HANDLER(0x15, bios_int15),
+};
+
+static void setup_irq_handler(struct kvm *kvm, struct irq_handler *handler)
+{
+	struct real_intr_desc intr_desc;
+	void *p;
+
+	p = guest_flat_to_host(kvm, handler->address);
+	memcpy(p, handler->handler, handler->size);
+
+	intr_desc = (struct real_intr_desc) {
+		.segment	= REAL_SEGMENT(MB_BIOS_BEGIN),
+		.offset		= handler->address - MB_BIOS_BEGIN,
+	};
+
+	DIE_IF((handler->address - MB_BIOS_BEGIN) > 0xffffUL);
+
+	interrupt_table__set(&kvm->interrupt_table, &intr_desc, handler->irq);
+}
+
+/**
+ * e820_setup - setup some simple E820 memory map
+ * @kvm - guest system descriptor
+ */
+static void e820_setup(struct kvm *kvm)
+{
+	struct e820map *e820;
+	struct e820entry *mem_map;
+	unsigned int i = 0;
+
+	e820		= guest_flat_to_host(kvm, E820_MAP_START);
+	mem_map		= e820->map;
+
+	mem_map[i++]	= (struct e820entry) {
+		.addr		= REAL_MODE_IVT_BEGIN,
+		.size		= EBDA_START - REAL_MODE_IVT_BEGIN,
+		.type		= E820_RAM,
+	};
+	mem_map[i++]	= (struct e820entry) {
+		.addr		= EBDA_START,
+		.size		= VGA_RAM_BEGIN - EBDA_START,
+		.type		= E820_RESERVED,
+	};
+	mem_map[i++]	= (struct e820entry) {
+		.addr		= MB_BIOS_BEGIN,
+		.size		= MB_BIOS_END - MB_BIOS_BEGIN,
+		.type		= E820_RESERVED,
+	};
+	if (kvm->ram_size < KVM_32BIT_GAP_START) {
+		mem_map[i++]	= (struct e820entry) {
+			.addr		= BZ_KERNEL_START,
+			.size		= kvm->ram_size - BZ_KERNEL_START,
+			.type		= E820_RAM,
+		};
+	} else {
+		mem_map[i++]	= (struct e820entry) {
+			.addr		= BZ_KERNEL_START,
+			.size		= KVM_32BIT_GAP_START - BZ_KERNEL_START,
+			.type		= E820_RAM,
+		};
+		mem_map[i++]	= (struct e820entry) {
+			.addr		= KVM_32BIT_MAX_MEM_SIZE,
+			.size		= kvm->ram_size - KVM_32BIT_MAX_MEM_SIZE,
+			.type		= E820_RAM,
+		};
+	}
+
+	BUG_ON(i > E820_X_MAX);
+
+	e820->nr_map = i;
+}
+
+static void setup_vga_rom(struct kvm *kvm)
+{
+	u16 *mode;
+	void *p;
+
+	p = guest_flat_to_host(kvm, VGA_ROM_OEM_STRING);
+	memset(p, 0, VGA_ROM_OEM_STRING_SIZE);
+	strncpy(p, "KVM VESA", VGA_ROM_OEM_STRING_SIZE);
+
+	mode = guest_flat_to_host(kvm, VGA_ROM_MODES);
+	mode[0]	= 0x0112;
+	mode[1] = 0xffff;
+}
+
+/**
+ * setup_bios - inject BIOS into guest memory
+ * @kvm - guest system descriptor
+ */
+void setup_bios(struct kvm *kvm)
+{
+	unsigned long address = MB_BIOS_BEGIN;
+	struct real_intr_desc intr_desc;
+	unsigned int i;
+	void *p;
+
+	/*
+	 * before anything else -- clean some known areas
+	 * we definitely don't want any trash here
+	 */
+	p = guest_flat_to_host(kvm, BDA_START);
+	memset(p, 0, BDA_END - BDA_START);
+
+	p = guest_flat_to_host(kvm, EBDA_START);
+	memset(p, 0, EBDA_END - EBDA_START);
+
+	p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
+	memset(p, 0, MB_BIOS_END - MB_BIOS_BEGIN);
+
+	p = guest_flat_to_host(kvm, VGA_ROM_BEGIN);
+	memset(p, 0, VGA_ROM_END - VGA_ROM_BEGIN);
+
+	/* just copy the bios rom into the place */
+	p = guest_flat_to_host(kvm, MB_BIOS_BEGIN);
+	memcpy(p, bios_rom, bios_rom_size);
+
+	/* E820 memory map must be present */
+	e820_setup(kvm);
+
+	/* VESA needs own tricks */
+	setup_vga_rom(kvm);
+
+	/*
+	 * Setup a *fake* real mode vector table, it has only
+	 * one real handler which does just iret
+	 */
+	address = BIOS_IRQ_PA_ADDR(bios_intfake);
+	intr_desc = (struct real_intr_desc) {
+		.segment	= REAL_SEGMENT(MB_BIOS_BEGIN),
+		.offset		= address - MB_BIOS_BEGIN,
+	};
+	interrupt_table__setup(&kvm->interrupt_table, &intr_desc);
+
+	for (i = 0; i < ARRAY_SIZE(bios_irq_handlers); i++)
+		setup_irq_handler(kvm, &bios_irq_handlers[i]);
+
+	/* we almost done */
+	p = guest_flat_to_host(kvm, 0);
+	interrupt_table__copy(&kvm->interrupt_table, p, REAL_INTR_SIZE);
+}
diff --git a/tools/kvm/x86/bios/.gitignore b/tools/kvm/x86/bios/.gitignore
new file mode 100644
index 0000000..1f0080b
--- /dev/null
+++ b/tools/kvm/x86/bios/.gitignore
@@ -0,0 +1,3 @@
+bios-rom.bin
+bios-rom.bin.elf
+bios-rom.h
diff --git a/tools/kvm/x86/bios/bios-rom.S b/tools/kvm/x86/bios/bios-rom.S
new file mode 100644
index 0000000..3269ce9
--- /dev/null
+++ b/tools/kvm/x86/bios/bios-rom.S
@@ -0,0 +1,12 @@
+#include <kvm/assembly.h>
+
+	.org 0
+#ifdef CONFIG_X86_64
+	.code64
+#else
+	.code32
+#endif
+
+GLOBAL(bios_rom)
+	.incbin "x86/bios/bios.bin"
+END(bios_rom)
diff --git a/tools/kvm/x86/bios/e820.c b/tools/kvm/x86/bios/e820.c
new file mode 100644
index 0000000..a9bca29
--- /dev/null
+++ b/tools/kvm/x86/bios/e820.c
@@ -0,0 +1,72 @@
+#include "kvm/e820.h"
+
+#include "kvm/segment.h"
+#include "kvm/bios.h"
+
+#include <asm/processor-flags.h>
+#include <asm/e820.h>
+
+static inline void set_fs(u16 seg)
+{
+	asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+
+static inline u8 rdfs8(unsigned long addr)
+{
+	u8 v;
+
+	asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+
+	return v;
+}
+
+static inline u32 rdfs32(unsigned long addr)
+{
+	u32 v;
+
+	asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(u32 *)addr));
+
+	return v;
+}
+
+bioscall void e820_query_map(struct biosregs *regs)
+{
+	struct e820map *e820;
+	u32 map_size;
+	u16 fs_seg;
+	u32 ndx;
+
+	e820		= (struct e820map *)E820_MAP_START;
+	fs_seg		= flat_to_seg16(E820_MAP_START);
+	set_fs(fs_seg);
+
+	ndx		= regs->ebx;
+
+	map_size	= rdfs32(flat_to_off16((u32)&e820->nr_map, fs_seg));
+
+	if (ndx < map_size) {
+		u32 start;
+		unsigned int i;
+		u8 *p;
+
+		fs_seg	= flat_to_seg16(E820_MAP_START);
+		set_fs(fs_seg);
+
+		start	= (u32)&e820->map[ndx];
+
+		p	= (void *) regs->edi;
+
+		for (i = 0; i < sizeof(struct e820entry); i++)
+			*p++	= rdfs8(flat_to_off16(start + i, fs_seg));
+	}
+
+	regs->eax	= SMAP;
+	regs->ecx	= sizeof(struct e820entry);
+	regs->ebx	= ++ndx;
+
+	/* Clear CF to indicate success.  */
+	regs->eflags	&= ~X86_EFLAGS_CF;
+
+	if (ndx >= map_size)
+		regs->ebx	= 0;	/* end of map */
+}
diff --git a/tools/kvm/x86/bios/entry.S b/tools/kvm/x86/bios/entry.S
new file mode 100644
index 0000000..85056e9
--- /dev/null
+++ b/tools/kvm/x86/bios/entry.S
@@ -0,0 +1,92 @@
+/*
+ * Our pretty trivial BIOS emulation
+ */
+
+#include <kvm/bios.h>
+#include <kvm/assembly.h>
+
+	.org 0
+	.code16gcc
+
+#define EFLAGS_CF	(1 << 0)
+
+#include "macro.S"
+
+/* If you change these macros, remember to update 'struct biosregs' */
+.macro SAVE_BIOSREGS
+	pushl	%fs
+	pushl	%es
+	pushl	%ds
+	pushl	%edi
+	pushl	%esi
+	pushl	%ebp
+	pushl	%esp
+	pushl	%edx
+	pushl	%ecx
+	pushl	%ebx
+	pushl	%eax
+.endm
+
+.macro RESTORE_BIOSREGS
+	popl	%eax
+	popl	%ebx
+	popl	%ecx
+	popl	%edx
+	popl	%esp
+	popl	%ebp
+	popl	%esi
+	popl	%edi
+	popl	%ds
+	popl	%es
+	popl	%fs
+.endm
+
+/*
+ * fake interrupt handler, nothing can be faster ever
+ */
+ENTRY(bios_intfake)
+	/*
+	 * Set CF to indicate failure. We don't want callers to think that the
+	 * interrupt handler succeeded and then treat the return values in
+	 * registers as valid data.
+	 */
+	orl	$EFLAGS_CF, 0x4(%esp)
+
+	IRET
+ENTRY_END(bios_intfake)
+
+/*
+ * int 10 - video - service
+ */
+ENTRY(bios_int10)
+	SAVE_BIOSREGS
+
+	movl		%esp, %eax
+	/* this is way easier than doing it in assembly */
+	/* just push all the regs and jump to a C handler */
+	call	int10_handler
+
+	RESTORE_BIOSREGS
+
+	/* Clear CF to indicate success.  */
+	andl	$~EFLAGS_CF, 0x4(%esp)
+
+	IRET
+ENTRY_END(bios_int10)
+
+ENTRY(bios_int15)
+	SAVE_BIOSREGS
+
+	movl	%esp, %eax
+	call	int15_handler
+
+	RESTORE_BIOSREGS
+
+	IRET
+ENTRY_END(bios_int15)
+
+GLOBAL(__locals)
+
+#include "local.S"
+
+END(__locals)
diff --git a/tools/kvm/x86/bios/gen-offsets.sh b/tools/kvm/x86/bios/gen-offsets.sh
new file mode 100644
index 0000000..8771bbe
--- /dev/null
+++ b/tools/kvm/x86/bios/gen-offsets.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+echo "/* Autogenerated file, don't edit */"
+echo "#ifndef BIOS_OFFSETS_H"
+echo "#define BIOS_OFFSETS_H"
+
+echo ""
+echo "#define BIOS_ENTRY_SIZE(name) (name##_end - name)"
+echo ""
+
+nm bios.bin.elf | grep ' [Tt] ' | awk '{ print "#define BIOS_OFFSET__" $3 " 0x" $1; }'
+
+echo ""
+echo "#endif"
diff --git a/tools/kvm/x86/bios/int10.c b/tools/kvm/x86/bios/int10.c
new file mode 100644
index 0000000..7cc0b3f
--- /dev/null
+++ b/tools/kvm/x86/bios/int10.c
@@ -0,0 +1,110 @@
+#include "kvm/segment.h"
+#include "kvm/bios.h"
+#include "kvm/vesa.h"
+
+#include "bios/memcpy.h"
+
+#include <boot/vesa.h>
+
+static far_ptr gen_far_ptr(unsigned int pa)
+{
+	far_ptr ptr;
+
+	ptr.seg = (pa >> 4);
+	ptr.off = pa - (ptr.seg << 4);
+
+	return ptr;
+}
+
+static inline void outb(unsigned short port, unsigned char val)
+{
+	asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
+}
+
+/*
+ * It's probably much more useful to make this print to the serial
+ * line rather than print to a non-displayed VGA memory
+ */
+static inline void int10_putchar(struct biosregs *args)
+{
+	u8 al = args->eax & 0xFF;
+
+	outb(0x3f8, al);
+}
+
+static void vbe_get_mode(struct biosregs *args)
+{
+	struct vesa_mode_info *info = (struct vesa_mode_info *) args->edi;
+
+	*info = (struct vesa_mode_info) {
+		.mode_attr		= 0xd9, /* 11011011 */
+		.logical_scan		= VESA_WIDTH*4,
+		.h_res			= VESA_WIDTH,
+		.v_res			= VESA_HEIGHT,
+		.bpp			= VESA_BPP,
+		.memory_layout		= 6,
+		.memory_planes		= 1,
+		.lfb_ptr		= VESA_MEM_ADDR,
+		.rmask			= 8,
+		.gmask			= 8,
+		.bmask			= 8,
+		.resv_mask		= 8,
+		.resv_pos		= 24,
+		.bpos			= 16,
+		.gpos			= 8,
+	};
+}
+
+static void vbe_get_info(struct biosregs *args)
+{
+	struct vesa_general_info *infop = (struct vesa_general_info *) args->edi;
+	struct vesa_general_info info;
+
+	info = (struct vesa_general_info) {
+		.signature		= VESA_MAGIC,
+		.version		= 0x102,
+		.vendor_string		= gen_far_ptr(VGA_ROM_BEGIN),
+		.capabilities		= 0x10,
+		.video_mode_ptr		= gen_far_ptr(VGA_ROM_MODES),
+		.total_memory		= (4 * VESA_WIDTH * VESA_HEIGHT) / 0x10000,
+	};
+
+	memcpy16(args->es, infop, args->ds, &info, sizeof(info));
+}
+
+#define VBE_STATUS_OK		0x004F
+
+static void int10_vesa(struct biosregs *args)
+{
+	u8 al;
+
+	al = args->eax & 0xff;
+
+	switch (al) {
+	case 0x00:
+		vbe_get_info(args);
+		break;
+	case 0x01:
+		vbe_get_mode(args);
+		break;
+	}
+
+	args->eax = VBE_STATUS_OK;
+}
+
+bioscall void int10_handler(struct biosregs *args)
+{
+	u8 ah;
+
+	ah = (args->eax & 0xff00) >> 8;
+
+	switch (ah) {
+	case 0x0e:
+		int10_putchar(args);
+		break;
+	case 0x4f:
+		int10_vesa(args);
+		break;
+	}
+
+}
diff --git a/tools/kvm/x86/bios/int15.c b/tools/kvm/x86/bios/int15.c
new file mode 100644
index 0000000..faf5343
--- /dev/null
+++ b/tools/kvm/x86/bios/int15.c
@@ -0,0 +1,18 @@
+#include "kvm/bios.h"
+
+#include "kvm/e820.h"
+
+#include <asm/processor-flags.h>
+
+bioscall void int15_handler(struct biosregs *regs)
+{
+	switch (regs->eax) {
+	case 0xe820:
+		e820_query_map(regs);
+		break;
+	default:
+		/* Set CF to indicate failure.  */
+		regs->eflags	|= X86_EFLAGS_CF;
+		break;
+	}
+}
diff --git a/tools/kvm/x86/bios/local.S b/tools/kvm/x86/bios/local.S
new file mode 100644
index 0000000..f2cdbf4
--- /dev/null
+++ b/tools/kvm/x86/bios/local.S
@@ -0,0 +1,7 @@
+/*
+ * Local variables for almost every BIOS irq handler
+ * Must be put somewhere inside irq handler body
+ */
+__CALLER_SS:		.int  0
+__CALLER_SP:		.long 0
+__CALLER_CLOBBER:	.long 0
diff --git a/tools/kvm/x86/bios/macro.S b/tools/kvm/x86/bios/macro.S
new file mode 100644
index 0000000..0d5e567e
--- /dev/null
+++ b/tools/kvm/x86/bios/macro.S
@@ -0,0 +1,25 @@
+/*
+ * handy BIOS macros
+ */
+
+/*
+ * switch to BIOS stack
+ */
+.macro stack_swap
+	movw %ss, %cs:(__CALLER_SS)
+	movl %esp, %cs:(__CALLER_SP)
+	movl %edx, %cs:(__CALLER_CLOBBER)
+	movw $MB_BIOS_SS, %dx
+	movw %dx, %ss
+	movw $MB_BIOS_SP, %sp
+	movl %cs:(__CALLER_CLOBBER), %edx
+.endm
+
+/*
+ * restore the original stack
+ */
+.macro stack_restore
+	movl %cs:(__CALLER_SP), %esp
+	movw %cs:(__CALLER_SS), %ss
+.endm
+
diff --git a/tools/kvm/x86/bios/memcpy.c b/tools/kvm/x86/bios/memcpy.c
new file mode 100644
index 0000000..40b9b65
--- /dev/null
+++ b/tools/kvm/x86/bios/memcpy.c
@@ -0,0 +1,23 @@
+#include "bios/memcpy.h"
+
+/*
+ *  Copy memory area in 16-bit real mode.
+ */
+void memcpy16(u16 dst_seg, void *dst, u16 src_seg, const void *src, size_t len)
+{
+	__asm__ __volatile__ (
+		"pushw	%%ds				\n"
+		"pushw	%%es				\n"
+		"movw	%[src_seg], %%ds		\n"
+		"movw	%[dst_seg], %%es		\n"
+		"rep movsb %%ds:(%%si), %%es:(%%di)	\n"
+		"popw	%%es				\n"
+		"popw	%%ds				\n"
+		:
+		: "S"(src),
+		  "D"(dst),
+		  "c"(len),
+		  [src_seg] "r"(src_seg),
+		  [dst_seg] "r"(dst_seg)
+		: "cc", "memory");
+}
diff --git a/tools/kvm/x86/bios/rom.ld.S b/tools/kvm/x86/bios/rom.ld.S
new file mode 100644
index 0000000..f122b97
--- /dev/null
+++ b/tools/kvm/x86/bios/rom.ld.S
@@ -0,0 +1,17 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+PHDRS {
+	text PT_LOAD FLAGS(5);		/* R_E */
+	data PT_LOAD FLAGS(7);		/* RWE */
+	user PT_LOAD FLAGS(5);		/* R_E */
+	percpu PT_LOAD FLAGS(6);	/* RW_ */
+	init PT_LOAD FLAGS(7);		/* RWE */
+	note PT_NOTE FLAGS(0);		/* ___ */
+}
+
+SECTIONS {
+	. = 0;
+	.text : { *(.text) } :text = 0x9090
+}
+
diff --git a/tools/kvm/x86/cpuid.c b/tools/kvm/x86/cpuid.c
new file mode 100644
index 0000000..75f3b4d
--- /dev/null
+++ b/tools/kvm/x86/cpuid.c
@@ -0,0 +1,55 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#define CPUID_FUNC_PERFMON		0x0A
+
+#define	MAX_KVM_CPUID_ENTRIES		100
+
+static void filter_cpuid(struct kvm_cpuid2 *kvm_cpuid)
+{
+	unsigned int i;
+
+	/*
+	 * Filter CPUID functions that are not supported by the hypervisor.
+	 */
+	for (i = 0; i < kvm_cpuid->nent; i++) {
+		struct kvm_cpuid_entry2 *entry = &kvm_cpuid->entries[i];
+
+		switch (entry->function) {
+		case 6:
+			/* Clear presence of IA32_ENERGY_PERF_BIAS */
+			entry->ecx = entry->ecx & ~(1 << 3);
+			break;
+		case CPUID_FUNC_PERFMON:
+			entry->eax = 0x00; /* disable it */
+			break;
+		default:
+			/* Keep the CPUID function as -is */
+			break;
+		};
+	}
+}
+
+void kvm_cpu__setup_cpuid(struct kvm_cpu *vcpu)
+{
+	struct kvm_cpuid2 *kvm_cpuid;
+
+	kvm_cpuid = calloc(1, sizeof(*kvm_cpuid) +
+				MAX_KVM_CPUID_ENTRIES * sizeof(*kvm_cpuid->entries));
+
+	kvm_cpuid->nent = MAX_KVM_CPUID_ENTRIES;
+	if (ioctl(vcpu->kvm->sys_fd, KVM_GET_SUPPORTED_CPUID, kvm_cpuid) < 0)
+		die_perror("KVM_GET_SUPPORTED_CPUID failed");
+
+	filter_cpuid(kvm_cpuid);
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_CPUID2, kvm_cpuid) < 0)
+		die_perror("KVM_SET_CPUID2 failed");
+
+	free(kvm_cpuid);
+}
diff --git a/tools/kvm/x86/include/kvm/assembly.h b/tools/kvm/x86/include/kvm/assembly.h
new file mode 100644
index 0000000..e70baab
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/assembly.h
@@ -0,0 +1,24 @@
+#ifndef ASSEMBLY_H_
+#define ASSEMBLY_H_
+
+#define __ALIGN	.p2align 4, 0x90
+#define ENTRY(name)	\
+	__ALIGN;	\
+	.globl name;	\
+	name:
+
+#define GLOBAL(name)	\
+	.globl name;	\
+	name:
+
+#define ENTRY_END(name)	GLOBAL(name##_end)
+#define END(name)	GLOBAL(name##_end)
+
+/*
+ * gas produces size override prefix with which
+ * we are unhappy, lets make it hardcoded for
+ * 16 bit mode
+ */
+#define IRET	.byte 0xcf
+
+#endif /* ASSEMBLY_H_ */
diff --git a/tools/kvm/x86/include/kvm/barrier.h b/tools/kvm/x86/include/kvm/barrier.h
new file mode 100644
index 0000000..480276f
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/barrier.h
@@ -0,0 +1,16 @@
+#ifndef _KVM_BARRIER_H_
+#define _KVM_BARRIER_H_
+
+/*
+ * asm/system.h cannot be #included standalone on 32-bit x86 yet.
+ *
+ * Provide the dependencies here - we can drop these wrappers once
+ * the header is fixed upstream:
+ */
+#include <stdbool.h>
+#include <linux/stringify.h>
+#include <linux/bitops.h>
+#include <asm/alternative.h>
+#include <asm/system.h>
+
+#endif /* _KVM_BARRIER_H_ */
diff --git a/tools/kvm/x86/include/kvm/bios-export.h b/tools/kvm/x86/include/kvm/bios-export.h
new file mode 100644
index 0000000..23825aa
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/bios-export.h
@@ -0,0 +1,13 @@
+#ifndef BIOS_EXPORT_H_
+#define BIOS_EXPORT_H_
+
+struct kvm;
+
+extern char bios_rom[0];
+extern char bios_rom_end[0];
+
+#define bios_rom_size		(bios_rom_end - bios_rom)
+
+extern void setup_bios(struct kvm *kvm);
+
+#endif /* BIOS_EXPORT_H_ */
diff --git a/tools/kvm/x86/include/kvm/bios.h b/tools/kvm/x86/include/kvm/bios.h
new file mode 100644
index 0000000..c12fba7
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/bios.h
@@ -0,0 +1,88 @@
+#ifndef BIOS_H_
+#define BIOS_H_
+
+/*
+ * X86-32 Memory Map (typical)
+ *					start      end
+ * Real Mode Interrupt Vector Table	0x00000000 0x000003FF
+ * BDA area				0x00000400 0x000004FF
+ * Conventional Low Memory		0x00000500 0x0009FBFF
+ * EBDA area				0x0009FC00 0x0009FFFF
+ * VIDEO RAM				0x000A0000 0x000BFFFF
+ * VIDEO ROM (BIOS)			0x000C0000 0x000C7FFF
+ * Motherboard BIOS			0x000F0000 0x000FFFFF
+ * Extended Memory			0x00100000 0xFEBFFFFF
+ * Reserved (configs, ACPI, PnP, etc)	0xFEC00000 0xFFFFFFFF
+ */
+
+#define REAL_MODE_IVT_BEGIN		0x00000000
+#define REAL_MODE_IVT_END		0x000003ff
+
+#define BDA_START			0x00000400
+#define BDA_END				0x000004ff
+
+#define EBDA_START			0x0009fc00
+#define EBDA_END			0x0009ffff
+
+#define E820_MAP_START			EBDA_START
+
+#define MB_BIOS_BEGIN			0x000f0000
+#define MB_BIOS_END			0x000fffff
+
+#define VGA_RAM_BEGIN			0x000a0000
+#define VGA_RAM_END			0x000bffff
+
+#define VGA_ROM_BEGIN			0x000c0000
+#define VGA_ROM_OEM_STRING		VGA_ROM_BEGIN
+#define VGA_ROM_OEM_STRING_SIZE		16
+#define VGA_ROM_MODES			(VGA_ROM_OEM_STRING + VGA_ROM_OEM_STRING_SIZE)
+#define VGA_ROM_MODES_SIZE		32
+#define VGA_ROM_END			0x000c7fff
+
+/* we handle one page only */
+#define VGA_RAM_SEG			(VGA_RAM_BEGIN >> 4)
+#define VGA_PAGE_SIZE			0x007d0 /* 80x25 */
+
+/* real mode interrupt vector table */
+#define REAL_INTR_BASE			REAL_MODE_IVT_BEGIN
+#define REAL_INTR_VECTORS		256
+
+/*
+ * BIOS stack must be at absolute predefined memory address
+ * We reserve 64 bytes for BIOS stack
+ */
+#define MB_BIOS_SS			0xfff7
+#define MB_BIOS_SP			0x40
+
+/*
+ * When interfere with assembler code we need to be sure how
+ * arguments are passed in real mode.
+ */
+#define bioscall __attribute__((regparm(3)))
+
+#ifndef __ASSEMBLER__
+
+#include <linux/types.h>
+
+struct biosregs {
+	u32			eax;
+	u32			ebx;
+	u32			ecx;
+	u32			edx;
+	u32			esp;
+	u32			ebp;
+	u32			esi;
+	u32			edi;
+	u32			ds;
+	u32			es;
+	u32			fs;
+	u32			eip;
+	u32			eflags;
+};
+
+void int10_handler(struct biosregs *regs);
+void int15_handler(struct biosregs *regs);
+
+#endif
+
+#endif /* BIOS_H_ */
diff --git a/tools/kvm/x86/include/kvm/boot-protocol.h b/tools/kvm/x86/include/kvm/boot-protocol.h
new file mode 100644
index 0000000..85b637f
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/boot-protocol.h
@@ -0,0 +1,16 @@
+/*
+ * Linux boot protocol specifics
+ */
+
+#ifndef BOOT_PROTOCOL_H_
+#define BOOT_PROTOCOL_H_
+
+/*
+ * The protected mode kernel part of a modern bzImage is loaded
+ * at 1 MB by default.
+ */
+#define BZ_DEFAULT_SETUP_SECTS		4
+#define BZ_KERNEL_START			0x100000UL
+#define INITRD_START			0x1000000UL
+
+#endif /* BOOT_PROTOCOL_H_ */
diff --git a/tools/kvm/x86/include/kvm/cpufeature.h b/tools/kvm/x86/include/kvm/cpufeature.h
new file mode 100644
index 0000000..bc4abbb
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/cpufeature.h
@@ -0,0 +1,41 @@
+#ifndef KVM__CPUFEATURE_H
+#define KVM__CPUFEATURE_H
+
+#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
+#define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
+#define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
+
+#define CPUID_VENDOR_AMD_1   0x68747541 /* "Auth" */
+#define CPUID_VENDOR_AMD_2   0x69746e65 /* "enti" */
+#define CPUID_VENDOR_AMD_3   0x444d4163 /* "cAMD" */
+
+/*
+ * CPUID flags we need to deal with
+ */
+#define KVM__X86_FEATURE_VMX		5	/* Hardware virtualization */
+#define KVM__X86_FEATURE_SVM		2	/* Secure virtual machine */
+#define KVM__X86_FEATURE_XSAVE		26	/* XSAVE/XRSTOR/XSETBV/XGETBV */
+
+#define cpu_feature_disable(reg, feature)	\
+	((reg) & ~(1 << (feature)))
+#define cpu_feature_enable(reg, feature)	\
+	((reg) |  (1 << (feature)))
+
+struct cpuid_regs {
+	u32	eax;
+	u32	ebx;
+	u32	ecx;
+	u32	edx;
+};
+
+static inline void host_cpuid(struct cpuid_regs *regs)
+{
+	asm volatile("cpuid"
+		: "=a" (regs->eax),
+		  "=b" (regs->ebx),
+		  "=c" (regs->ecx),
+		  "=d" (regs->edx)
+		: "0" (regs->eax), "2" (regs->ecx));
+}
+
+#endif /* KVM__CPUFEATURE_H */
diff --git a/tools/kvm/x86/include/kvm/interrupt.h b/tools/kvm/x86/include/kvm/interrupt.h
new file mode 100644
index 0000000..00c7ed7
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/interrupt.h
@@ -0,0 +1,26 @@
+#ifndef KVM__INTERRUPT_H
+#define KVM__INTERRUPT_H
+
+#include <linux/types.h>
+#include "kvm/bios.h"
+#include "kvm/bios-export.h"
+
+struct real_intr_desc {
+	u16 offset;
+	u16 segment;
+} __attribute__((packed));
+
+#define REAL_SEGMENT_SHIFT	4
+#define REAL_SEGMENT(addr)	((addr) >> REAL_SEGMENT_SHIFT)
+#define REAL_OFFSET(addr)	((addr) & ((1 << REAL_SEGMENT_SHIFT) - 1))
+#define REAL_INTR_SIZE		(REAL_INTR_VECTORS * sizeof(struct real_intr_desc))
+
+struct interrupt_table {
+	struct real_intr_desc entries[REAL_INTR_VECTORS];
+};
+
+void interrupt_table__copy(struct interrupt_table *itable, void *dst, unsigned int size);
+void interrupt_table__setup(struct interrupt_table *itable, struct real_intr_desc *entry);
+void interrupt_table__set(struct interrupt_table *itable, struct real_intr_desc *entry, unsigned int num);
+
+#endif /* KVM__INTERRUPT_H */
diff --git a/tools/kvm/x86/include/kvm/kvm-arch.h b/tools/kvm/x86/include/kvm/kvm-arch.h
new file mode 100644
index 0000000..ba04561
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/kvm-arch.h
@@ -0,0 +1,65 @@
+#ifndef KVM__KVM_ARCH_H
+#define KVM__KVM_ARCH_H
+
+#include "kvm/interrupt.h"
+#include "kvm/segment.h"
+
+#include <stdbool.h>
+#include <linux/types.h>
+#include <time.h>
+
+/*
+ * The hole includes VESA framebuffer and PCI memory.
+ */
+#define KVM_32BIT_MAX_MEM_SIZE  (1ULL << 32)
+#define KVM_32BIT_GAP_SIZE	(768 << 20)
+#define KVM_32BIT_GAP_START	(KVM_32BIT_MAX_MEM_SIZE - KVM_32BIT_GAP_SIZE)
+
+#define KVM_MMIO_START		KVM_32BIT_GAP_START
+
+/* This is the address that pci_get_io_space_block() starts allocating
+ * from.  Note that this is a PCI bus address (though same on x86).
+ */
+#define KVM_PCI_MMIO_AREA	(KVM_MMIO_START + 0x1000000)
+
+struct kvm {
+	int			sys_fd;		/* For system ioctls(), i.e. /dev/kvm */
+	int			vm_fd;		/* For VM ioctls() */
+	timer_t			timerid;	/* Posix timer for interrupts */
+
+	int			nrcpus;		/* Number of cpus to run */
+
+	u32			mem_slots;	/* for KVM_SET_USER_MEMORY_REGION */
+
+	u64			ram_size;
+	void			*ram_start;
+
+	bool			nmi_disabled;
+
+	bool			single_step;
+
+	u16			boot_selector;
+	u16			boot_ip;
+	u16			boot_sp;
+
+	struct interrupt_table	interrupt_table;
+
+	const char		*vmlinux;
+	struct disk_image       **disks;
+	int                     nr_disks;
+
+	const char		*name;
+
+	int			vm_state;
+};
+
+static inline void *guest_flat_to_host(struct kvm *kvm, unsigned long offset); /* In kvm.h */
+
+static inline void *guest_real_to_host(struct kvm *kvm, u16 selector, u16 offset)
+{
+	unsigned long flat = segment_to_flat(selector, offset);
+
+	return guest_flat_to_host(kvm, flat);
+}
+
+#endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/x86/include/kvm/kvm-cpu-arch.h b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
new file mode 100644
index 0000000..198efe6
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/kvm-cpu-arch.h
@@ -0,0 +1,49 @@
+#ifndef KVM__KVM_CPU_ARCH_H
+#define KVM__KVM_CPU_ARCH_H
+
+/* Architecture-specific kvm_cpu definitions. */
+
+#include <linux/kvm.h>	/* for struct kvm_regs */
+#include "kvm/kvm.h"	/* for kvm__emulate_{mm}io() */
+#include <stdbool.h>
+#include <pthread.h>
+
+struct kvm;
+
+struct kvm_cpu {
+	pthread_t		thread;		/* VCPU thread */
+
+	unsigned long		cpu_id;
+
+	struct kvm		*kvm;		/* parent KVM */
+	int			vcpu_fd;	/* For VCPU ioctls() */
+	struct kvm_run		*kvm_run;
+
+	struct kvm_regs		regs;
+	struct kvm_sregs	sregs;
+	struct kvm_fpu		fpu;
+
+	struct kvm_msrs		*msrs;		/* dynamically allocated */
+
+	u8			is_running;
+	u8			paused;
+	u8			needs_nmi;
+
+	struct kvm_coalesced_mmio_ring	*ring;
+};
+
+/*
+ * As these are such simple wrappers, let's have them in the header so they'll
+ * be cheaper to call:
+ */
+static inline bool kvm_cpu__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int size, u32 count)
+{
+	return kvm__emulate_io(kvm, port, data, direction, size, count);
+}
+
+static inline bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write)
+{
+	return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write);
+}
+
+#endif /* KVM__KVM_CPU_ARCH_H */
diff --git a/tools/kvm/x86/include/kvm/mptable.h b/tools/kvm/x86/include/kvm/mptable.h
new file mode 100644
index 0000000..8f04332
--- /dev/null
+++ b/tools/kvm/x86/include/kvm/mptable.h
@@ -0,0 +1,8 @@
+#ifndef KVM_MPTABLE_H_
+#define KVM_MPTABLE_H_
+
+struct kvm;
+
+int mptable_setup(struct kvm *kvm, unsigned int ncpus);
+
+#endif /* KVM_MPTABLE_H_ */
diff --git a/tools/kvm/x86/interrupt.c b/tools/kvm/x86/interrupt.c
new file mode 100644
index 0000000..7d47869
--- /dev/null
+++ b/tools/kvm/x86/interrupt.c
@@ -0,0 +1,28 @@
+#include "kvm/interrupt.h"
+
+#include "kvm/util.h"
+
+#include <string.h>
+
+void interrupt_table__copy(struct interrupt_table *itable, void *dst, unsigned int size)
+{
+	if (size < sizeof(itable->entries))
+		die("An attempt to overwrite host memory");
+
+	memcpy(dst, itable->entries, sizeof(itable->entries));
+}
+
+void interrupt_table__setup(struct interrupt_table *itable, struct real_intr_desc *entry)
+{
+	unsigned int i;
+
+	for (i = 0; i < REAL_INTR_VECTORS; i++)
+		itable->entries[i] = *entry;
+}
+
+void interrupt_table__set(struct interrupt_table *itable,
+				struct real_intr_desc *entry, unsigned int num)
+{
+	if (num < REAL_INTR_VECTORS)
+		itable->entries[num] = *entry;
+}
diff --git a/tools/kvm/x86/ioport.c b/tools/kvm/x86/ioport.c
new file mode 100644
index 0000000..8a91bf2
--- /dev/null
+++ b/tools/kvm/x86/ioport.c
@@ -0,0 +1,59 @@
+#include "kvm/ioport.h"
+
+#include <stdlib.h>
+
+static bool debug_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	exit(EXIT_SUCCESS);
+}
+
+static struct ioport_operations debug_ops = {
+	.io_out		= debug_io_out,
+};
+
+static bool dummy_io_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	return true;
+}
+
+static bool dummy_io_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size)
+{
+	return true;
+}
+
+static struct ioport_operations dummy_read_write_ioport_ops = {
+	.io_in		= dummy_io_in,
+	.io_out		= dummy_io_out,
+};
+
+static struct ioport_operations dummy_write_only_ioport_ops = {
+	.io_out		= dummy_io_out,
+};
+
+void ioport__setup_arch(void)
+{
+	/* Legacy ioport setup */
+
+	/* 0x0020 - 0x003F - 8259A PIC 1 */
+	ioport__register(0x0020, &dummy_read_write_ioport_ops, 2, NULL);
+
+	/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
+	ioport__register(0x0040, &dummy_read_write_ioport_ops, 4, NULL);
+
+	/* 0x00A0 - 0x00AF - 8259A PIC 2 */
+	ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2, NULL);
+
+	/* PORT 00E0-00EF are 'motherboard specific' so we use them for our
+	   internal debugging purposes.  */
+	ioport__register(IOPORT_DBG, &debug_ops, 1, NULL);
+
+	/* PORT 00ED - DUMMY PORT FOR DELAY??? */
+	ioport__register(0x00ED, &dummy_write_only_ioport_ops, 1, NULL);
+
+	/* 0x00F0 - 0x00FF - Math co-processor */
+	ioport__register(0x00F0, &dummy_write_only_ioport_ops, 2, NULL);
+
+	/* PORT 03D4-03D5 - COLOR VIDEO - CRT CONTROL REGISTERS */
+	ioport__register(0x03D4, &dummy_read_write_ioport_ops, 1, NULL);
+	ioport__register(0x03D5, &dummy_write_only_ioport_ops, 1, NULL);
+}
diff --git a/tools/kvm/x86/irq.c b/tools/kvm/x86/irq.c
new file mode 100644
index 0000000..b8a7257
--- /dev/null
+++ b/tools/kvm/x86/irq.c
@@ -0,0 +1,193 @@
+#include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
+
+#include <linux/types.h>
+#include <linux/rbtree.h>
+#include <linux/list.h>
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#define IRQ_MAX_GSI			64
+#define IRQCHIP_MASTER			0
+#define IRQCHIP_SLAVE			1
+#define IRQCHIP_IOAPIC			2
+
+static u8		next_line	= 5;
+static u8		next_dev	= 1;
+static struct rb_root	pci_tree	= RB_ROOT;
+
+/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
+static u32 gsi = 24;
+
+struct kvm_irq_routing *irq_routing;
+
+static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
+{
+	if (gsi >= IRQ_MAX_GSI)
+		return -ENOSPC;
+
+	irq_routing->entries[irq_routing->nr++] =
+		(struct kvm_irq_routing_entry) {
+			.gsi = gsi,
+			.type = type,
+			.u.irqchip.irqchip = irqchip,
+			.u.irqchip.pin = pin,
+		};
+
+	return 0;
+}
+
+static struct pci_dev *search(struct rb_root *root, u32 id)
+{
+	struct rb_node *node = root->rb_node;
+
+	while (node) {
+		struct pci_dev *data = container_of(node, struct pci_dev, node);
+		int result;
+
+		result = id - data->id;
+
+		if (result < 0)
+			node = node->rb_left;
+		else if (result > 0)
+			node = node->rb_right;
+		else
+			return data;
+	}
+	return NULL;
+}
+
+static int insert(struct rb_root *root, struct pci_dev *data)
+{
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+	/* Figure out where to put new node */
+	while (*new) {
+		struct pci_dev *this	= container_of(*new, struct pci_dev, node);
+		int result		= data->id - this->id;
+
+		parent = *new;
+		if (result < 0)
+			new = &((*new)->rb_left);
+		else if (result > 0)
+			new = &((*new)->rb_right);
+		else
+			return 0;
+	}
+
+	/* Add new node and rebalance tree. */
+	rb_link_node(&data->node, parent, new);
+	rb_insert_color(&data->node, root);
+
+	return 1;
+}
+
+int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
+{
+	struct pci_dev *node;
+
+	node = search(&pci_tree, dev);
+
+	if (!node) {
+		/* We haven't found a node - First device of it's kind */
+		node = malloc(sizeof(*node));
+		if (node == NULL)
+			return -1;
+
+		*node = (struct pci_dev) {
+			.id	= dev,
+			/*
+			 * PCI supports only INTA#,B#,C#,D# per device.
+			 * A#,B#,C#,D# are allowed for multifunctional
+			 * devices so stick with A# for our single
+			 * function devices.
+			 */
+			.pin	= 1,
+		};
+
+		INIT_LIST_HEAD(&node->lines);
+
+		if (insert(&pci_tree, node) != 1) {
+			free(node);
+			return -1;
+		}
+	}
+
+	if (node) {
+		/* This device already has a pin assigned, give out a new line and device id */
+		struct irq_line *new = malloc(sizeof(*new));
+		if (new == NULL)
+			return -1;
+
+		new->line	= next_line++;
+		*line		= new->line;
+		*pin		= node->pin;
+		*num		= next_dev++;
+
+		list_add(&new->node, &node->lines);
+
+		return 0;
+	}
+
+	return -1;
+}
+
+void irq__init(struct kvm *kvm)
+{
+	int i, r;
+
+	irq_routing = calloc(sizeof(struct kvm_irq_routing) +
+			IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry), 1);
+	if (irq_routing == NULL)
+		die("Failed allocating space for GSI table");
+
+	/* Hook first 8 GSIs to master IRQCHIP */
+	for (i = 0; i < 8; i++)
+		if (i != 2)
+			irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i);
+
+	/* Hook next 8 GSIs to slave IRQCHIP */
+	for (i = 8; i < 16; i++)
+		irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, i - 8);
+
+	/* Last but not least, IOAPIC */
+	for (i = 0; i < 24; i++) {
+		if (i == 0)
+			irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2);
+		else if (i != 2)
+			irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i);
+	}
+
+	r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+	if (r)
+		die("Failed setting GSI routes");
+}
+
+int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
+{
+	int r;
+
+	irq_routing->entries[irq_routing->nr++] =
+		(struct kvm_irq_routing_entry) {
+			.gsi = gsi,
+			.type = KVM_IRQ_ROUTING_MSI,
+			.u.msi.address_hi = msg->address_hi,
+			.u.msi.address_lo = msg->address_lo,
+			.u.msi.data = msg->data,
+		};
+
+	r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+	if (r)
+		return r;
+
+	return gsi++;
+}
+
+struct rb_node *irq__get_pci_tree(void)
+{
+	return rb_first(&pci_tree);
+}
diff --git a/tools/kvm/x86/kvm-cpu.c b/tools/kvm/x86/kvm-cpu.c
new file mode 100644
index 0000000..051699f
--- /dev/null
+++ b/tools/kvm/x86/kvm-cpu.c
@@ -0,0 +1,421 @@
+#include "kvm/kvm-cpu.h"
+
+#include "kvm/symbol.h"
+#include "kvm/util.h"
+#include "kvm/kvm.h"
+
+#include <asm/msr-index.h>
+#include <asm/apicdef.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+static int debug_fd;
+
+void kvm_cpu__set_debug_fd(int fd)
+{
+	debug_fd = fd;
+}
+
+int kvm_cpu__get_debug_fd(void)
+{
+	return debug_fd;
+}
+
+static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
+{
+	return vcpu->sregs.cr0 & 0x01;
+}
+
+static inline u64 ip_to_flat(struct kvm_cpu *vcpu, u64 ip)
+{
+	u64 cs;
+
+	/*
+	 * NOTE! We should take code segment base address into account here.
+	 * Luckily it's usually zero because Linux uses flat memory model.
+	 */
+	if (is_in_protected_mode(vcpu))
+		return ip;
+
+	cs = vcpu->sregs.cs.selector;
+
+	return ip + (cs << 4);
+}
+
+static inline u32 selector_to_base(u16 selector)
+{
+	/*
+	 * KVM on Intel requires 'base' to be 'selector * 16' in real mode.
+	 */
+	return (u32)selector << 4;
+}
+
+static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
+{
+	struct kvm_cpu *vcpu;
+
+	vcpu = calloc(1, sizeof(*vcpu));
+	if (!vcpu)
+		return NULL;
+
+	vcpu->kvm = kvm;
+
+	return vcpu;
+}
+
+void kvm_cpu__delete(struct kvm_cpu *vcpu)
+{
+	if (vcpu->msrs)
+		free(vcpu->msrs);
+
+	free(vcpu);
+}
+
+static int kvm_cpu__set_lint(struct kvm_cpu *vcpu)
+{
+	struct local_apic lapic;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_LAPIC, &lapic))
+		return -1;
+
+	lapic.lvt_lint0.delivery_mode = APIC_MODE_EXTINT;
+	lapic.lvt_lint1.delivery_mode = APIC_MODE_NMI;
+
+	return ioctl(vcpu->vcpu_fd, KVM_SET_LAPIC, &lapic);
+}
+
+struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
+{
+	struct kvm_cpu *vcpu;
+	int mmap_size;
+	int coalesced_offset;
+
+	vcpu = kvm_cpu__new(kvm);
+	if (!vcpu)
+		return NULL;
+
+	vcpu->cpu_id = cpu_id;
+
+	vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
+	if (vcpu->vcpu_fd < 0)
+		die_perror("KVM_CREATE_VCPU ioctl");
+
+	mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
+	if (mmap_size < 0)
+		die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
+
+	vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
+	if (vcpu->kvm_run == MAP_FAILED)
+		die("unable to mmap vcpu fd");
+
+	coalesced_offset = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_COALESCED_MMIO);
+	if (coalesced_offset)
+		vcpu->ring = (void *)vcpu->kvm_run + (coalesced_offset * PAGE_SIZE);
+
+	if (kvm_cpu__set_lint(vcpu))
+		die_perror("KVM_SET_LAPIC failed");
+
+	vcpu->is_running = true;
+
+	return vcpu;
+}
+
+static struct kvm_msrs *kvm_msrs__new(size_t nmsrs)
+{
+	struct kvm_msrs *vcpu = calloc(1, sizeof(*vcpu) + (sizeof(struct kvm_msr_entry) * nmsrs));
+
+	if (!vcpu)
+		die("out of memory");
+
+	return vcpu;
+}
+
+#define KVM_MSR_ENTRY(_index, _data)	\
+	(struct kvm_msr_entry) { .index = _index, .data = _data }
+
+static void kvm_cpu__setup_msrs(struct kvm_cpu *vcpu)
+{
+	unsigned long ndx = 0;
+
+	vcpu->msrs = kvm_msrs__new(100);
+
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_CS,	0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_ESP,	0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_SYSENTER_EIP,	0x0);
+#ifdef CONFIG_X86_64
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_STAR,			0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_CSTAR,			0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_KERNEL_GS_BASE,		0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_SYSCALL_MASK,		0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_LSTAR,			0x0);
+#endif
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_TSC,		0x0);
+	vcpu->msrs->entries[ndx++] = KVM_MSR_ENTRY(MSR_IA32_MISC_ENABLE,
+						MSR_IA32_MISC_ENABLE_FAST_STRING);
+
+	vcpu->msrs->nmsrs = ndx;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_MSRS, vcpu->msrs) < 0)
+		die_perror("KVM_SET_MSRS failed");
+}
+
+static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
+{
+	vcpu->fpu = (struct kvm_fpu) {
+		.fcw	= 0x37f,
+		.mxcsr	= 0x1f80,
+	};
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_FPU, &vcpu->fpu) < 0)
+		die_perror("KVM_SET_FPU failed");
+}
+
+static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
+{
+	vcpu->regs = (struct kvm_regs) {
+		/* We start the guest in 16-bit real mode  */
+		.rflags	= 0x0000000000000002ULL,
+
+		.rip	= vcpu->kvm->boot_ip,
+		.rsp	= vcpu->kvm->boot_sp,
+		.rbp	= vcpu->kvm->boot_sp,
+	};
+
+	if (vcpu->regs.rip > USHRT_MAX)
+		die("ip 0x%llx is too high for real mode", (u64)vcpu->regs.rip);
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
+		die_perror("KVM_SET_REGS failed");
+}
+
+static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
+{
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+		die_perror("KVM_GET_SREGS failed");
+
+	vcpu->sregs.cs.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.cs.base	= selector_to_base(vcpu->kvm->boot_selector);
+	vcpu->sregs.ss.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.ss.base	= selector_to_base(vcpu->kvm->boot_selector);
+	vcpu->sregs.ds.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.ds.base	= selector_to_base(vcpu->kvm->boot_selector);
+	vcpu->sregs.es.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.es.base	= selector_to_base(vcpu->kvm->boot_selector);
+	vcpu->sregs.fs.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.fs.base	= selector_to_base(vcpu->kvm->boot_selector);
+	vcpu->sregs.gs.selector	= vcpu->kvm->boot_selector;
+	vcpu->sregs.gs.base	= selector_to_base(vcpu->kvm->boot_selector);
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_SREGS, &vcpu->sregs) < 0)
+		die_perror("KVM_SET_SREGS failed");
+}
+
+/**
+ * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
+ */
+void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
+{
+	kvm_cpu__setup_cpuid(vcpu);
+	kvm_cpu__setup_sregs(vcpu);
+	kvm_cpu__setup_regs(vcpu);
+	kvm_cpu__setup_fpu(vcpu);
+	kvm_cpu__setup_msrs(vcpu);
+}
+
+bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
+{
+	return false;
+}
+
+static void print_dtable(const char *name, struct kvm_dtable *dtable)
+{
+	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
+		name, (u64) dtable->base, (u16) dtable->limit);
+}
+
+static void print_segment(const char *name, struct kvm_segment *seg)
+{
+	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
+		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
+		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
+}
+
+void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
+{
+	unsigned long cr0, cr2, cr3;
+	unsigned long cr4, cr8;
+	unsigned long rax, rbx, rcx;
+	unsigned long rdx, rsi, rdi;
+	unsigned long rbp,  r8,  r9;
+	unsigned long r10, r11, r12;
+	unsigned long r13, r14, r15;
+	unsigned long rip, rsp;
+	struct kvm_sregs sregs;
+	unsigned long rflags;
+	struct kvm_regs regs;
+	int i;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
+		die("KVM_GET_REGS failed");
+
+	rflags = regs.rflags;
+
+	rip = regs.rip; rsp = regs.rsp;
+	rax = regs.rax; rbx = regs.rbx; rcx = regs.rcx;
+	rdx = regs.rdx; rsi = regs.rsi; rdi = regs.rdi;
+	rbp = regs.rbp; r8  = regs.r8;  r9  = regs.r9;
+	r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
+	r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
+
+	dprintf(debug_fd, "\n Registers:\n");
+	dprintf(debug_fd,   " ----------\n");
+	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
+	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
+	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
+	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
+	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
+	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
+		die("KVM_GET_REGS failed");
+
+	cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
+	cr4 = sregs.cr4; cr8 = sregs.cr8;
+
+	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
+	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
+	dprintf(debug_fd, "\n Segment registers:\n");
+	dprintf(debug_fd,   " ------------------\n");
+	dprintf(debug_fd, " register  selector  base              limit     type  p dpl db s l g avl\n");
+	print_segment("cs ", &sregs.cs);
+	print_segment("ss ", &sregs.ss);
+	print_segment("ds ", &sregs.ds);
+	print_segment("es ", &sregs.es);
+	print_segment("fs ", &sregs.fs);
+	print_segment("gs ", &sregs.gs);
+	print_segment("tr ", &sregs.tr);
+	print_segment("ldt", &sregs.ldt);
+	print_dtable("gdt", &sregs.gdt);
+	print_dtable("idt", &sregs.idt);
+
+	dprintf(debug_fd, "\n APIC:\n");
+	dprintf(debug_fd,   " -----\n");
+	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
+		(u64) sregs.efer, (u64) sregs.apic_base,
+		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
+
+	dprintf(debug_fd, "\n Interrupt bitmap:\n");
+	dprintf(debug_fd,   " -----------------\n");
+	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
+		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
+	dprintf(debug_fd, "\n");
+}
+
+#define MAX_SYM_LEN 128
+
+void kvm_cpu__show_code(struct kvm_cpu *vcpu)
+{
+	unsigned int code_bytes = 64;
+	unsigned int code_prologue = 43;
+	unsigned int code_len = code_bytes;
+	char sym[MAX_SYM_LEN];
+	unsigned char c;
+	unsigned int i;
+	u8 *ip;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
+		die("KVM_GET_REGS failed");
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+		die("KVM_GET_SREGS failed");
+
+	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
+
+	dprintf(debug_fd, "\n Code:\n");
+	dprintf(debug_fd,   " -----\n");
+
+	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
+
+	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
+
+	for (i = 0; i < code_len; i++, ip++) {
+		if (!host_ptr_in_ram(vcpu->kvm, ip))
+			break;
+
+		c = *ip;
+
+		if (ip == guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
+			dprintf(debug_fd, " <%02x>", c);
+		else
+			dprintf(debug_fd, " %02x", c);
+	}
+
+	dprintf(debug_fd, "\n");
+
+	dprintf(debug_fd, "\n Stack:\n");
+	dprintf(debug_fd,   " ------\n");
+	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
+}
+
+void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
+{
+	u64 *pte1;
+	u64 *pte2;
+	u64 *pte3;
+	u64 *pte4;
+
+	if (!is_in_protected_mode(vcpu))
+		return;
+
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &vcpu->sregs) < 0)
+		die("KVM_GET_SREGS failed");
+
+	pte4 = guest_flat_to_host(vcpu->kvm, vcpu->sregs.cr3);
+	if (!host_ptr_in_ram(vcpu->kvm, pte4))
+		return;
+
+	pte3 = guest_flat_to_host(vcpu->kvm, (*pte4 & ~0xfff));
+	if (!host_ptr_in_ram(vcpu->kvm, pte3))
+		return;
+
+	pte2 = guest_flat_to_host(vcpu->kvm, (*pte3 & ~0xfff));
+	if (!host_ptr_in_ram(vcpu->kvm, pte2))
+		return;
+
+	pte1 = guest_flat_to_host(vcpu->kvm, (*pte2 & ~0xfff));
+	if (!host_ptr_in_ram(vcpu->kvm, pte1))
+		return;
+
+	dprintf(debug_fd, "Page Tables:\n");
+	if (*pte2 & (1 << 7))
+		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
+			"   pte2: %016llx\n",
+			*pte4, *pte3, *pte2);
+	else
+		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
+			"llx   pte1: %016llx\n",
+			*pte4, *pte3, *pte2, *pte1);
+}
+
+void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
+{
+	struct kvm_lapic_state klapic;
+	struct local_apic *lapic = (void *)&klapic;
+
+	if (ioctl(cpu->vcpu_fd, KVM_GET_LAPIC, &klapic) != 0)
+		return;
+
+	if (lapic->lvt_lint1.mask)
+		return;
+
+	if (lapic->lvt_lint1.delivery_mode != APIC_MODE_NMI)
+		return;
+
+	ioctl(cpu->vcpu_fd, KVM_NMI);
+}
diff --git a/tools/kvm/x86/kvm.c b/tools/kvm/x86/kvm.c
new file mode 100644
index 0000000..a218881
--- /dev/null
+++ b/tools/kvm/x86/kvm.c
@@ -0,0 +1,374 @@
+#include "kvm/kvm.h"
+#include "kvm/boot-protocol.h"
+#include "kvm/cpufeature.h"
+#include "kvm/interrupt.h"
+#include "kvm/mptable.h"
+#include "kvm/util.h"
+#include "kvm/8250-serial.h"
+#include "kvm/virtio-console.h"
+
+#include <asm/bootparam.h>
+#include <linux/kvm.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+struct kvm_ext kvm_req_ext[] = {
+	{ DEFINE_KVM_EXT(KVM_CAP_COALESCED_MMIO) },
+	{ DEFINE_KVM_EXT(KVM_CAP_SET_TSS_ADDR) },
+	{ DEFINE_KVM_EXT(KVM_CAP_PIT2) },
+	{ DEFINE_KVM_EXT(KVM_CAP_USER_MEMORY) },
+	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_ROUTING) },
+	{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
+	{ DEFINE_KVM_EXT(KVM_CAP_HLT) },
+	{ DEFINE_KVM_EXT(KVM_CAP_IRQ_INJECT_STATUS) },
+	{ DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) },
+	{ 0, 0 }
+};
+
+bool kvm__arch_cpu_supports_vm(void)
+{
+	struct cpuid_regs regs;
+	u32 eax_base;
+	int feature;
+
+	regs	= (struct cpuid_regs) {
+		.eax		= 0x00,
+	};
+	host_cpuid(&regs);
+
+	switch (regs.ebx) {
+	case CPUID_VENDOR_INTEL_1:
+		eax_base	= 0x00;
+		feature		= KVM__X86_FEATURE_VMX;
+		break;
+
+	case CPUID_VENDOR_AMD_1:
+		eax_base	= 0x80000000;
+		feature		= KVM__X86_FEATURE_SVM;
+		break;
+
+	default:
+		return false;
+	}
+
+	regs	= (struct cpuid_regs) {
+		.eax		= eax_base,
+	};
+	host_cpuid(&regs);
+
+	if (regs.eax < eax_base + 0x01)
+		return false;
+
+	regs	= (struct cpuid_regs) {
+		.eax		= eax_base + 0x01
+	};
+	host_cpuid(&regs);
+
+	return regs.ecx & (1 << feature);
+}
+
+/*
+ * Allocating RAM size bigger than 4GB requires us to leave a gap
+ * in the RAM which is used for PCI MMIO, hotplug, and unconfigured
+ * devices (see documentation of e820_setup_gap() for details).
+ *
+ * If we're required to initialize RAM bigger than 4GB, we will create
+ * a gap between 0xe0000000 and 0x100000000 in the guest virtual mem space.
+ */
+
+void kvm__init_ram(struct kvm *kvm)
+{
+	u64	phys_start, phys_size;
+	void	*host_mem;
+
+	if (kvm->ram_size < KVM_32BIT_GAP_START) {
+		/* Use a single block of RAM for 32bit RAM */
+
+		phys_start = 0;
+		phys_size  = kvm->ram_size;
+		host_mem   = kvm->ram_start;
+
+		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+	} else {
+		/* First RAM range from zero to the PCI gap: */
+
+		phys_start = 0;
+		phys_size  = KVM_32BIT_GAP_START;
+		host_mem   = kvm->ram_start;
+
+		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+
+		/* Second RAM range from 4GB to the end of RAM: */
+
+		phys_start = KVM_32BIT_MAX_MEM_SIZE;
+		phys_size  = kvm->ram_size - phys_start;
+		host_mem   = kvm->ram_start + phys_start;
+
+		kvm__register_mem(kvm, phys_start, phys_size, host_mem);
+	}
+}
+
+/* Arch-specific commandline setup */
+void kvm__arch_set_cmdline(char *cmdline, bool video)
+{
+	strcpy(cmdline, "noapic noacpi pci=conf1 reboot=k panic=1 i8042.direct=1 "
+				"i8042.dumbkbd=1 i8042.nopnp=1");
+	if (video)
+		strcat(cmdline, " video=vesafb console=tty0");
+	else
+		strcat(cmdline, " console=ttyS0 earlyprintk=serial i8042.noaux=1");
+}
+
+/* This function wraps the decision between hugetlbfs map (if requested) or normal mmap */
+static void *mmap_anon_or_hugetlbfs(const char *hugetlbfs_path, u64 size)
+{
+	if (hugetlbfs_path)
+		/*
+		 * We don't /need/ to map guest RAM from hugetlbfs, but we do so
+		 * if the user specifies a hugetlbfs path.
+		 */
+		return mmap_hugetlbfs(hugetlbfs_path, size);
+	else
+		return mmap(NULL, size, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
+}
+
+/* Architecture-specific KVM init */
+void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
+{
+	struct kvm_pit_config pit_config = { .flags = 0, };
+	int ret;
+
+	ret = ioctl(kvm->vm_fd, KVM_SET_TSS_ADDR, 0xfffbd000);
+	if (ret < 0)
+		die_perror("KVM_SET_TSS_ADDR ioctl");
+
+	ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config);
+	if (ret < 0)
+		die_perror("KVM_CREATE_PIT2 ioctl");
+
+	if (ram_size < KVM_32BIT_GAP_START) {
+        kvm->ram_size = ram_size;
+		kvm->ram_start = mmap_anon_or_hugetlbfs(hugetlbfs_path, ram_size);
+	} else {
+		kvm->ram_start = mmap_anon_or_hugetlbfs(hugetlbfs_path, ram_size + KVM_32BIT_GAP_SIZE);
+        kvm->ram_size = ram_size + KVM_32BIT_GAP_SIZE;
+		if (kvm->ram_start != MAP_FAILED)
+			/*
+			 * We mprotect the gap (see kvm__init_ram() for details) PROT_NONE so that
+			 * if we accidently write to it, we will know.
+			 */
+			mprotect(kvm->ram_start + KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, PROT_NONE);
+	}
+	if (kvm->ram_start == MAP_FAILED)
+		die("out of memory");
+
+	madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
+
+	ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP);
+	if (ret < 0)
+		die_perror("KVM_CREATE_IRQCHIP ioctl");
+}
+
+void kvm__arch_delete_ram(struct kvm *kvm)
+{
+	if (kvm->ram_size < KVM_32BIT_GAP_START)
+		munmap(kvm->ram_start, kvm->ram_size);
+	else
+		munmap(kvm->ram_start, kvm->ram_size + KVM_32BIT_GAP_SIZE);
+}
+
+void kvm__irq_line(struct kvm *kvm, int irq, int level)
+{
+	struct kvm_irq_level irq_level;
+
+	irq_level	= (struct kvm_irq_level) {
+		{
+			.irq		= irq,
+		},
+		.level		= level,
+	};
+
+	if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0)
+		die_perror("KVM_IRQ_LINE failed");
+}
+
+void kvm__irq_trigger(struct kvm *kvm, int irq)
+{
+	kvm__irq_line(kvm, irq, 1);
+	kvm__irq_line(kvm, irq, 0);
+}
+
+#define BOOT_LOADER_SELECTOR	0x1000
+#define BOOT_LOADER_IP		0x0000
+#define BOOT_LOADER_SP		0x8000
+#define BOOT_CMDLINE_OFFSET	0x20000
+
+#define BOOT_PROTOCOL_REQUIRED	0x206
+#define LOAD_HIGH		0x01
+
+int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
+{
+	void *p;
+	int nr;
+
+	/*
+	 * Some architectures may support loading an initrd alongside the flat kernel,
+	 * but we do not.
+	 */
+	if (fd_initrd != -1)
+		pr_warning("Loading initrd with flat binary not supported.");
+
+	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+		die_perror("lseek");
+
+	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
+
+	while ((nr = read(fd_kernel, p, 65536)) > 0)
+		p += nr;
+
+	kvm->boot_selector	= BOOT_LOADER_SELECTOR;
+	kvm->boot_ip		= BOOT_LOADER_IP;
+	kvm->boot_sp		= BOOT_LOADER_SP;
+
+	return true;
+}
+
+static const char *BZIMAGE_MAGIC = "HdrS";
+
+bool load_bzimage(struct kvm *kvm, int fd_kernel,
+		  int fd_initrd, const char *kernel_cmdline, u16 vidmode)
+{
+	struct boot_params *kern_boot;
+	unsigned long setup_sects;
+	struct boot_params boot;
+	size_t cmdline_size;
+	ssize_t setup_size;
+	void *p;
+	int nr;
+
+	/*
+	 * See Documentation/x86/boot.txt for details no bzImage on-disk and
+	 * memory layout.
+	 */
+
+	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+		die_perror("lseek");
+
+	if (read(fd_kernel, &boot, sizeof(boot)) != sizeof(boot))
+		return false;
+
+	if (memcmp(&boot.hdr.header, BZIMAGE_MAGIC, strlen(BZIMAGE_MAGIC)))
+		return false;
+
+	if (boot.hdr.version < BOOT_PROTOCOL_REQUIRED)
+		die("Too old kernel");
+
+	if (lseek(fd_kernel, 0, SEEK_SET) < 0)
+		die_perror("lseek");
+
+	if (!boot.hdr.setup_sects)
+		boot.hdr.setup_sects = BZ_DEFAULT_SETUP_SECTS;
+	setup_sects = boot.hdr.setup_sects + 1;
+
+	setup_size = setup_sects << 9;
+	p = guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, BOOT_LOADER_IP);
+
+	/* copy setup.bin to mem*/
+	if (read(fd_kernel, p, setup_size) != setup_size)
+		die_perror("read");
+
+	/* copy vmlinux.bin to BZ_KERNEL_START*/
+	p = guest_flat_to_host(kvm, BZ_KERNEL_START);
+
+	while ((nr = read(fd_kernel, p, 65536)) > 0)
+		p += nr;
+
+	p = guest_flat_to_host(kvm, BOOT_CMDLINE_OFFSET);
+	if (kernel_cmdline) {
+		cmdline_size = strlen(kernel_cmdline) + 1;
+		if (cmdline_size > boot.hdr.cmdline_size)
+			cmdline_size = boot.hdr.cmdline_size;
+
+		memset(p, 0, boot.hdr.cmdline_size);
+		memcpy(p, kernel_cmdline, cmdline_size - 1);
+	}
+
+	kern_boot	= guest_real_to_host(kvm, BOOT_LOADER_SELECTOR, 0x00);
+
+	kern_boot->hdr.cmd_line_ptr	= BOOT_CMDLINE_OFFSET;
+	kern_boot->hdr.type_of_loader	= 0xff;
+	kern_boot->hdr.heap_end_ptr	= 0xfe00;
+	kern_boot->hdr.loadflags	|= CAN_USE_HEAP;
+	kern_boot->hdr.vid_mode		= vidmode;
+
+	/*
+	 * Read initrd image into guest memory
+	 */
+	if (fd_initrd >= 0) {
+		struct stat initrd_stat;
+		unsigned long addr;
+
+		if (fstat(fd_initrd, &initrd_stat))
+			die_perror("fstat");
+
+		addr = boot.hdr.initrd_addr_max & ~0xfffff;
+		for (;;) {
+			if (addr < BZ_KERNEL_START)
+				die("Not enough memory for initrd");
+			else if (addr < (kvm->ram_size - initrd_stat.st_size))
+				break;
+			addr -= 0x100000;
+		}
+
+		p = guest_flat_to_host(kvm, addr);
+		nr = read(fd_initrd, p, initrd_stat.st_size);
+		if (nr != initrd_stat.st_size)
+			die("Failed to read initrd");
+
+		kern_boot->hdr.ramdisk_image	= addr;
+		kern_boot->hdr.ramdisk_size	= initrd_stat.st_size;
+	}
+
+	kvm->boot_selector = BOOT_LOADER_SELECTOR;
+	/*
+	 * The real-mode setup code starts at offset 0x200 of a bzImage. See
+	 * Documentation/x86/boot.txt for details.
+	 */
+	kvm->boot_ip = BOOT_LOADER_IP + 0x200;
+	kvm->boot_sp = BOOT_LOADER_SP;
+
+	return true;
+}
+
+/**
+ * kvm__arch_setup_firmware - inject BIOS into guest system memory
+ * @kvm - guest system descriptor
+ *
+ * This function is a main routine where we poke guest memory
+ * and install BIOS there.
+ */
+int kvm__arch_setup_firmware(struct kvm *kvm)
+{
+	/* standart minimal configuration */
+	setup_bios(kvm);
+
+	/* FIXME: SMP, ACPI and friends here */
+
+	/* MP table */
+	return mptable_setup(kvm, kvm->nrcpus);
+}
+
+void kvm__arch_periodic_poll(struct kvm *kvm)
+{
+	serial8250__update_consoles(kvm);
+	virtio_console__inject_interrupt(kvm);
+}
diff --git a/tools/kvm/x86/mptable.c b/tools/kvm/x86/mptable.c
new file mode 100644
index 0000000..c775829
--- /dev/null
+++ b/tools/kvm/x86/mptable.c
@@ -0,0 +1,280 @@
+#include "kvm/kvm.h"
+#include "kvm/bios.h"
+#include "kvm/apic.h"
+#include "kvm/mptable.h"
+#include "kvm/util.h"
+#include "kvm/irq.h"
+
+#include <linux/kernel.h>
+#include <string.h>
+
+#include <asm/mpspec_def.h>
+#include <linux/types.h>
+
+/*
+ * FIXME: please make sure the addresses borrowed
+ * for apic/ioapic never overlaped! We need a global
+ * tracker of system resources (including io, mmio,
+ * and friends).
+ */
+
+static unsigned int mpf_checksum(unsigned char *mp, int len)
+{
+	unsigned int sum = 0;
+
+	while (len--)
+		sum += *mp++;
+
+	return sum & 0xFF;
+}
+
+static unsigned int gen_cpu_flag(unsigned int cpu, unsigned int ncpu)
+{
+	/* sets enabled/disabled | BSP/AP processor */
+	return ( (cpu < ncpu) ? CPU_ENABLED       : 0) |
+		((cpu == 0)   ? CPU_BOOTPROCESSOR : 0x00);
+}
+
+#define MPTABLE_SIG_FLOATING	"_MP_"
+#define MPTABLE_OEM		"KVMCPU00"
+#define MPTABLE_PRODUCTID	"0.1         "
+#define MPTABLE_PCIBUSTYPE	"PCI   "
+#define MPTABLE_ISABUSTYPE	"ISA   "
+
+#define MPTABLE_STRNCPY(d, s)	memcpy(d, s, sizeof(d))
+
+/* It should be more than enough */
+#define MPTABLE_MAX_SIZE	(32 << 20)
+
+/*
+ * Too many cpus will require x2apic mode
+ * and rather ACPI support so we limit it
+ * here for a while.
+ */
+#define MPTABLE_MAX_CPUS	255
+
+static void mptable_add_irq_src(struct mpc_intsrc *mpc_intsrc,
+				u16 srcbusid,	u16 srcbusirq,
+				u16 dstapic,	u16 dstirq)
+{
+	*mpc_intsrc = (struct mpc_intsrc) {
+		.type		= MP_INTSRC,
+		.irqtype	= mp_INT,
+		.irqflag	= MP_IRQDIR_DEFAULT,
+		.srcbus		= srcbusid,
+		.srcbusirq	= srcbusirq,
+		.dstapic	= dstapic,
+		.dstirq		= dstirq
+	};
+}
+
+/**
+ * mptable_setup - create mptable and fill guest memory with it
+ */
+int mptable_setup(struct kvm *kvm, unsigned int ncpus)
+{
+	unsigned long real_mpc_table, real_mpf_intel, size;
+	struct mpf_intel *mpf_intel;
+	struct mpc_table *mpc_table;
+	struct mpc_cpu *mpc_cpu;
+	struct mpc_bus *mpc_bus;
+	struct mpc_ioapic *mpc_ioapic;
+	struct mpc_intsrc *mpc_intsrc;
+	struct rb_node *pci_tree;
+
+	const int pcibusid = 0;
+	const int isabusid = 1;
+
+	unsigned int i, nentries = 0;
+	unsigned int ioapicid;
+	void *last_addr;
+
+	/* That is where MP table will be in guest memory */
+	real_mpc_table = ALIGN(MB_BIOS_BEGIN + bios_rom_size, 16);
+
+	if (ncpus > MPTABLE_MAX_CPUS) {
+		pr_warning("Too many cpus: %d limited to %d",
+			ncpus, MPTABLE_MAX_CPUS);
+		ncpus = MPTABLE_MAX_CPUS;
+	}
+
+	mpc_table = calloc(1, MPTABLE_MAX_SIZE);
+	if (!mpc_table)
+		die("Out of memory");
+
+	MPTABLE_STRNCPY(mpc_table->signature,	MPC_SIGNATURE);
+	MPTABLE_STRNCPY(mpc_table->oem,		MPTABLE_OEM);
+	MPTABLE_STRNCPY(mpc_table->productid,	MPTABLE_PRODUCTID);
+
+	mpc_table->spec		= 4;
+	mpc_table->lapic	= APIC_ADDR(0);
+	mpc_table->oemcount	= ncpus; /* will be updated again at end */
+
+	/*
+	 * CPUs enumeration. Technically speaking we should
+	 * ask either host or HV for apic version supported
+	 * but for a while we simply put some random value
+	 * here.
+	 */
+	mpc_cpu = (void *)&mpc_table[1];
+	for (i = 0; i < ncpus; i++) {
+		mpc_cpu->type		= MP_PROCESSOR;
+		mpc_cpu->apicid		= i;
+		mpc_cpu->apicver	= KVM_APIC_VERSION;
+		mpc_cpu->cpuflag	= gen_cpu_flag(i, ncpus);
+		mpc_cpu->cpufeature	= 0x600; /* some default value */
+		mpc_cpu->featureflag	= 0x201; /* some default value */
+		mpc_cpu++;
+	}
+
+	last_addr = (void *)mpc_cpu;
+	nentries += ncpus;
+
+	/*
+	 * PCI buses.
+	 * FIXME: Some callback here to obtain real number
+	 * of PCI buses present in system.
+	 */
+	mpc_bus		= last_addr;
+	mpc_bus->type	= MP_BUS;
+	mpc_bus->busid	= pcibusid;
+	MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_PCIBUSTYPE);
+
+	last_addr = (void *)&mpc_bus[1];
+	nentries++;
+
+	/*
+	 * ISA bus.
+	 * FIXME: Same issue as for PCI bus.
+	 */
+	mpc_bus		= last_addr;
+	mpc_bus->type	= MP_BUS;
+	mpc_bus->busid	= isabusid;
+	MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_ISABUSTYPE);
+
+	last_addr = (void *)&mpc_bus[1];
+	nentries++;
+
+	/*
+	 * IO-APIC chip.
+	 */
+	ioapicid		= ncpus + 1;
+	mpc_ioapic		= last_addr;
+	mpc_ioapic->type	= MP_IOAPIC;
+	mpc_ioapic->apicid	= ioapicid;
+	mpc_ioapic->apicver	= KVM_APIC_VERSION;
+	mpc_ioapic->flags	= MPC_APIC_USABLE;
+	mpc_ioapic->apicaddr	= IOAPIC_ADDR(0);
+
+	last_addr = (void *)&mpc_ioapic[1];
+	nentries++;
+
+	/*
+	 * IRQ sources.
+	 *
+	 * FIXME: Same issue as with buses. We definitely
+	 * need kind of collector routine which enumerate
+	 * resources used first and pass them here.
+	 * At moment we know we have only virtio block device
+	 * and virtio console but this is g00berfish.
+	 *
+	 * Also note we use PCI irqs here, no for ISA bus yet.
+	 */
+
+	for (pci_tree = irq__get_pci_tree(); pci_tree; pci_tree = rb_next(pci_tree)) {
+		struct pci_dev *dev = rb_entry(pci_tree, struct pci_dev, node);
+		struct irq_line *irq_line;
+
+		list_for_each_entry(irq_line, &dev->lines, node) {
+			unsigned char srcbusirq;
+
+			srcbusirq = (dev->id << 2) | (dev->pin - 1);
+
+			mpc_intsrc = last_addr;
+
+			mptable_add_irq_src(mpc_intsrc, pcibusid, srcbusirq, ioapicid, irq_line->line);
+			last_addr = (void *)&mpc_intsrc[1];
+			nentries++;
+		}
+	}
+
+	/*
+	 * Local IRQs assignment (LINT0, LINT1)
+	 */
+	mpc_intsrc		= last_addr;
+	mpc_intsrc->type	= MP_LINTSRC;
+	mpc_intsrc->irqtype	= mp_ExtINT;
+	mpc_intsrc->irqtype	= mp_INT;
+	mpc_intsrc->irqflag	= MP_IRQDIR_DEFAULT;
+	mpc_intsrc->srcbus	= isabusid;
+	mpc_intsrc->srcbusirq	= 0;
+	mpc_intsrc->dstapic	= 0; /* FIXME: BSP apic */
+	mpc_intsrc->dstirq	= 0; /* LINT0 */
+
+	last_addr = (void *)&mpc_intsrc[1];
+	nentries++;
+
+	mpc_intsrc		= last_addr;
+	mpc_intsrc->type	= MP_LINTSRC;
+	mpc_intsrc->irqtype	= mp_NMI;
+	mpc_intsrc->irqflag	= MP_IRQDIR_DEFAULT;
+	mpc_intsrc->srcbus	= isabusid;
+	mpc_intsrc->srcbusirq	= 0;
+	mpc_intsrc->dstapic	= 0; /* FIXME: BSP apic */
+	mpc_intsrc->dstirq	= 1; /* LINT1 */
+
+	last_addr = (void *)&mpc_intsrc[1];
+	nentries++;
+
+	/*
+	 * Floating MP table finally.
+	 */
+	real_mpf_intel	= ALIGN((unsigned long)last_addr - (unsigned long)mpc_table, 16);
+	mpf_intel	= (void *)((unsigned long)mpc_table + real_mpf_intel);
+
+	MPTABLE_STRNCPY(mpf_intel->signature, MPTABLE_SIG_FLOATING);
+	mpf_intel->length	= 1;
+	mpf_intel->specification= 4;
+	mpf_intel->physptr	= (unsigned int)real_mpc_table;
+	mpf_intel->checksum	= -mpf_checksum((unsigned char *)mpf_intel, sizeof(*mpf_intel));
+
+	/*
+	 * No last_addr inclrement here please, we need last
+	 * active position here to compute table size.
+	 */
+
+	/*
+	 * Don't forget to update header in fixed table.
+	*/
+	mpc_table->oemcount	= nentries;
+	mpc_table->length	= last_addr - (void *)mpc_table;
+	mpc_table->checksum	= -mpf_checksum((unsigned char *)mpc_table, mpc_table->length);
+
+
+	/*
+	 * We will copy the whole table, no need to separate
+	 * floating structure and table itkvm.
+	 */
+	size = (unsigned long)mpf_intel + sizeof(*mpf_intel) - (unsigned long)mpc_table;
+
+	/*
+	 * The finial check -- never get out of system bios
+	 * area. Lets also check for allocated memory overrun,
+	 * in real it's late but still usefull.
+	 */
+
+	if (size > (unsigned long)(MB_BIOS_END - bios_rom_size) ||
+	    size > MPTABLE_MAX_SIZE) {
+		free(mpc_table);
+		pr_err("MP table is too big");
+		return -1;
+	}
+
+	/*
+	 * OK, it is time to move it to guest memory.
+	 */
+	memcpy(guest_flat_to_host(kvm, real_mpc_table), mpc_table, size);
+
+	free(mpc_table);
+	return 0;
+}
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 2780d9c..be88378 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -78,6 +78,8 @@ OPTIONS
 -F::
 --funcs::
 	Show available functions in given module or kernel.
+	With -x/--exec, can also list functions in a user space executable
+	/ shared library.
 
 --filter=FILTER::
 	(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
@@ -98,6 +100,11 @@ OPTIONS
 --max-probes::
 	Set the maximum number of probe points for an event. Default is 128.
 
+-x::
+--exec=PATH::
+	Specify path to the executable or shared library file for user
+	space tracing. Can also be used with --funcs option.
+
 PROBE SYNTAX
 ------------
 Probe points are defined by following syntax.
@@ -182,6 +189,13 @@ Delete all probes on schedule().
 
  ./perf probe --del='schedule*'
 
+Add probes at zfree() function on /bin/zsh
+
+ ./perf probe -x /bin/zsh zfree
+
+Add probes at malloc() function on libc
+
+ ./perf probe -x /lib/libc.so.6 malloc
 
 SEE ALSO
 --------
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 59d43ab..6edd8a3 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -56,11 +56,12 @@ static struct {
 	bool show_ext_vars;
 	bool show_funcs;
 	bool mod_events;
+	bool uprobes;
 	int nevents;
 	struct perf_probe_event events[MAX_PROBES];
 	struct strlist *dellist;
 	struct line_range line_range;
-	const char *target_module;
+	const char *target;
 	int max_probe_points;
 	struct strfilter *filter;
 } params;
@@ -77,6 +78,7 @@ static int parse_probe_event(const char *str)
 		return -1;
 	}
 
+	pev->uprobes = params.uprobes;
 	/* Parse a perf-probe command into event */
 	ret = parse_perf_probe_command(str, pev);
 	pr_debug("%d arguments\n", pev->nargs);
@@ -127,6 +129,27 @@ static int opt_del_probe_event(const struct option *opt __used,
 	return 0;
 }
 
+static int opt_set_target(const struct option *opt, const char *str,
+			int unset __used)
+{
+	int ret = -ENOENT;
+
+	if  (str && !params.target) {
+		if (!strcmp(opt->long_name, "exec"))
+			params.uprobes = true;
+#ifdef DWARF_SUPPORT
+		else if (!strcmp(opt->long_name, "module"))
+			params.uprobes = false;
+#endif
+		else
+			return ret;
+
+		params.target = str;
+		ret = 0;
+	}
+	return ret;
+}
+
 #ifdef DWARF_SUPPORT
 static int opt_show_lines(const struct option *opt __used,
 			  const char *str, int unset __used)
@@ -248,9 +271,9 @@ static const struct option options[] = {
 		   "file", "vmlinux pathname"),
 	OPT_STRING('s', "source", &symbol_conf.source_prefix,
 		   "directory", "path to kernel source"),
-	OPT_STRING('m', "module", &params.target_module,
-		   "modname|path",
-		   "target module name (for online) or path (for offline)"),
+	OPT_CALLBACK('m', "module", NULL, "modname|path",
+		"target module name (for online) or path (for offline)",
+		opt_set_target),
 #endif
 	OPT__DRY_RUN(&probe_event_dry_run),
 	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
@@ -262,6 +285,8 @@ static const struct option options[] = {
 		     "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
 		     "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
 		     opt_set_filter),
+	OPT_CALLBACK('x', "exec", NULL, "executable|path",
+			"target executable name or path", opt_set_target),
 	OPT_END()
 };
 
@@ -312,6 +337,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			pr_err("  Error: Don't use --list with --funcs.\n");
 			usage_with_options(probe_usage, options);
 		}
+		if (params.uprobes) {
+			pr_warning("  Error: Don't use --list with --exec.\n");
+			usage_with_options(probe_usage, options);
+		}
 		ret = show_perf_probe_events();
 		if (ret < 0)
 			pr_err("  Error: Failed to show event list. (%d)\n",
@@ -335,8 +364,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 		if (!params.filter)
 			params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
 						       NULL);
-		ret = show_available_funcs(params.target_module,
-					   params.filter);
+		ret = show_available_funcs(params.target, params.filter,
+					params.uprobes);
 		strfilter__delete(params.filter);
 		if (ret < 0)
 			pr_err("  Error: Failed to show functions."
@@ -345,7 +374,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 	}
 
 #ifdef DWARF_SUPPORT
-	if (params.show_lines) {
+	if (params.show_lines && !params.uprobes) {
 		if (params.mod_events) {
 			pr_err("  Error: Don't use --line with"
 			       " --add/--del.\n");
@@ -356,7 +385,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			usage_with_options(probe_usage, options);
 		}
 
-		ret = show_line_range(&params.line_range, params.target_module);
+		ret = show_line_range(&params.line_range, params.target);
 		if (ret < 0)
 			pr_err("  Error: Failed to show lines. (%d)\n", ret);
 		return ret;
@@ -373,7 +402,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 
 		ret = show_available_vars(params.events, params.nevents,
 					  params.max_probe_points,
-					  params.target_module,
+					  params.target,
 					  params.filter,
 					  params.show_ext_vars);
 		strfilter__delete(params.filter);
@@ -395,7 +424,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 	if (params.nevents) {
 		ret = add_perf_probe_events(params.events, params.nevents,
 					    params.max_probe_points,
-					    params.target_module,
+					    params.target,
 					    params.force_add);
 		if (ret < 0) {
 			pr_err("  Error: Failed to add events. (%d)\n", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0abfb18..a4f257e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -385,7 +385,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 {
 	struct stat st;
 	int flags;
-	int err, output;
+	int err, output, feat;
 	unsigned long waking = 0;
 	const bool forks = argc > 0;
 	struct machine *machine;
@@ -452,8 +452,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 
 	rec->session = session;
 
-	if (!rec->no_buildid)
-		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
+	for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
+		perf_header__set_feat(&session->header, feat);
+
+	if (rec->no_buildid)
+		perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
+
+	if (!have_tracepoints(&evsel_list->entries))
+		perf_header__clear_feat(&session->header, HEADER_TRACE_INFO);
 
 	if (!rec->file_new) {
 		err = perf_session__read_header(session, output);
@@ -461,22 +467,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
 			goto out_delete_session;
 	}
 
-	if (have_tracepoints(&evsel_list->entries))
-		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
-
-	perf_header__set_feat(&session->header, HEADER_HOSTNAME);
-	perf_header__set_feat(&session->header, HEADER_OSRELEASE);
-	perf_header__set_feat(&session->header, HEADER_ARCH);
-	perf_header__set_feat(&session->header, HEADER_CPUDESC);
-	perf_header__set_feat(&session->header, HEADER_NRCPUS);
-	perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
-	perf_header__set_feat(&session->header, HEADER_CMDLINE);
-	perf_header__set_feat(&session->header, HEADER_VERSION);
-	perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
-	perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
-	perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
-	perf_header__set_feat(&session->header, HEADER_CPUID);
-
 	if (forks) {
 		err = perf_evlist__prepare_workload(evsel_list, opts, argv);
 		if (err < 0) {
diff --git a/tools/perf/scripts/perl/bin/ibs-record b/tools/perf/scripts/perl/bin/ibs-record
new file mode 100644
index 0000000..dc5f4d2
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/ibs-record
@@ -0,0 +1,23 @@
+#! /bin/bash
+
+while [ "${1+defined}" ]; do
+    case $1 in
+	ibs_op|ibs_fetch)
+	    EVENT=$1
+	    shift
+	    break
+	    ;;
+	-*)
+	    REC_OPT+=($1)
+	    shift
+	    ;;
+	*)
+	    echo $0 "$@" >&2
+	    echo "Invalid option: $1" >&2
+	    echo "perf script ibs [ibs_op|ibs_fetch] [-c <period>]" >&2
+	    exit 1
+	    ;;
+    esac
+done
+
+perf record -e ${EVENT:-ibs_op}:r0 -c 100000 -R -a "${REC_OPT[@]}" "$@"
diff --git a/tools/perf/scripts/perl/bin/ibs-report b/tools/perf/scripts/perl/bin/ibs-report
new file mode 100644
index 0000000..f44e69d
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/ibs-report
@@ -0,0 +1,6 @@
+#! /bin/bash
+
+# description: collect and display AMD IBS samples
+# args: [ibs_op|ibs_fetch] [-c period]
+
+perf script -s "$PERF_EXEC_PATH"/scripts/perl/ibs.pl "$@"
diff --git a/tools/perf/scripts/perl/ibs.pl b/tools/perf/scripts/perl/ibs.pl
new file mode 100644
index 0000000..caee32f
--- /dev/null
+++ b/tools/perf/scripts/perl/ibs.pl
@@ -0,0 +1,47 @@
+#
+# ibs.pl - perf script for AMD Instruction Based Sampling
+#
+# Copyright (C) 2011 Advanced Micro Devices, Inc., Robert Richter
+#
+# For licencing details see kernel-base/COPYING
+#
+# description: collect and display AMD IBS samples
+# args: [ibs_op|ibs_fetch] [-c period]
+#
+# examples:
+#
+#  perf script ibs ibs_op <command>
+#  perf script ibs ibs_fetch <command>
+#  perf script record ibs ibs_op -c 500000 <command>
+#  perf script report ibs
+#  perf script record ibs ibs_op -c 500000 <command> | perf script report ibs
+#
+
+# Packed byte string args of process_event():
+#
+# $event:	union perf_event	util/event.h
+# $attr:	struct perf_event_attr	linux/perf_event.h
+# $sample:	struct perf_sample	util/event.h
+# $raw_data:	perf_sample->raw_data	util/event.h
+
+sub process_event
+{
+	my ($event, $attr, $sample, $raw_data) = @_;
+
+	my ($type)		= (unpack("LSS", $event))[0];
+	my ($sample_type)	= (unpack("LLQQQQQLLQQ", $attr))[4];
+	my ($cpu, $raw_size)	= (unpack("QLLQQQQQLL", $sample))[8, 9];
+	my ($caps, @ibs_data)	= unpack("LQ*", $raw_data);
+
+	return if (!$raw_size);		# no raw data
+
+	if (scalar(@ibs_data) ==  3) {
+	        printf("IBS_FETCH sample on cpu%d\tIBS0: 0x%016x IBS1: 0x%016x IBS2:0x%016x\n",
+		       $cpu, @ibs_data);
+	} else {
+	        printf("IBS_OP sample on cpu%d\t" .
+		       "\t IBS0: 0x%016x IBS1: 0x%016x IBS2: 0x%016x\n" .
+		       "\tIBS3: 0x%016x IBS4: 0x%016x IBS5: 0x%016x IBS6: 0x%016x\n",
+		       cpu, @ibs_data);
+	}
+}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e7e0b0..0a6f061 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -988,6 +988,73 @@ done:
 	return ret;
 }
 
+#define EVENT_SOURCE_DEVICE_PATH "/sys/bus/event_source/devices/"
+
+/*
+ * File format:
+ *
+ * struct pmu_mappings {
+ *	u32	pmu_num;
+ *	struct pmu_map {
+ *		u32	type;
+ *		char	name[];
+ *	}[pmu_num];
+ * };
+ */
+
+static int write_pmu_mappings(int fd, struct perf_header *h __used,
+			      struct perf_evlist *evlist __used)
+{
+	char path[MAXPATHLEN];
+	DIR *dir;
+	struct dirent *dent;
+	FILE *fp;
+	char *line = NULL;
+	off_t offset = lseek(fd, 0, SEEK_CUR);
+	size_t ignore;
+	u32 pmu_num = 0;
+	u32 type;
+
+	dir = opendir(EVENT_SOURCE_DEVICE_PATH);
+	if (!dir)
+		return -1;
+
+	/* write real pmu_num later */
+	do_write(fd, &pmu_num, sizeof(pmu_num));
+
+	while ((dent = readdir(dir))) {
+		if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+			continue;
+		snprintf(path, sizeof(path), "%s%s/type",
+			 EVENT_SOURCE_DEVICE_PATH, dent->d_name);
+		fp = fopen(path, "r");
+		if (!fp)
+			continue;
+		if (getline(&line, &ignore, fp) < 0) {
+			fclose(fp);
+			continue;
+		}
+		fclose(fp);
+		type = atoi(line);
+		if (!type)
+			continue;
+		pmu_num++;
+		do_write(fd, &type, sizeof(type));
+		do_write_string(fd, dent->d_name);
+	}
+
+	free(line);
+	closedir(dir);
+
+	if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
+		/* discard all */
+		lseek(fd, offset, SEEK_SET);
+		return -1;
+	}
+
+	return 0;
+}
+
 /*
  * default get_cpuid(): nothing gets recorded
  * actual implementation must be in arch/$(ARCH)/util/header.c
@@ -1305,25 +1372,229 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
 	free(str);
 }
 
+static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
+{
+	const char *delimiter = "# pmu mappings: ";
+	char *name;
+	int ret;
+	u32 pmu_num;
+	u32 type;
+
+	ret = read(fd, &pmu_num, sizeof(pmu_num));
+	if (ret != sizeof(pmu_num))
+		goto error;
+
+	if (!pmu_num)
+		goto error;
+
+	while (pmu_num--) {
+		if (read(fd, &type, sizeof(type)) != sizeof(type))
+			goto error;
+		name = do_read_string(fd, ph);
+		fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type);
+		free(name);
+		delimiter = ", ";
+	}
+
+	fprintf(fp, "\n");
+
+	return;
+error:
+	fprintf(fp, "# pmu mappings: not available\n");
+}
+
+static int __event_process_build_id(struct build_id_event *bev,
+				    char *filename,
+				    struct perf_session *session)
+{
+	int err = -1;
+	struct list_head *head;
+	struct machine *machine;
+	u16 misc;
+	struct dso *dso;
+	enum dso_kernel_type dso_type;
+
+	machine = perf_session__findnew_machine(session, bev->pid);
+	if (!machine)
+		goto out;
+
+	misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+
+	switch (misc) {
+	case PERF_RECORD_MISC_KERNEL:
+		dso_type = DSO_TYPE_KERNEL;
+		head = &machine->kernel_dsos;
+		break;
+	case PERF_RECORD_MISC_GUEST_KERNEL:
+		dso_type = DSO_TYPE_GUEST_KERNEL;
+		head = &machine->kernel_dsos;
+		break;
+	case PERF_RECORD_MISC_USER:
+	case PERF_RECORD_MISC_GUEST_USER:
+		dso_type = DSO_TYPE_USER;
+		head = &machine->user_dsos;
+		break;
+	default:
+		goto out;
+	}
+
+	dso = __dsos__findnew(head, filename);
+	if (dso != NULL) {
+		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
+		dso__set_build_id(dso, &bev->build_id);
+
+		if (filename[0] == '[')
+			dso->kernel = dso_type;
+
+		build_id__sprintf(dso->build_id, sizeof(dso->build_id),
+				  sbuild_id);
+		pr_debug("build id event received for %s: %s\n",
+			 dso->long_name, sbuild_id);
+	}
+
+	err = 0;
+out:
+	return err;
+}
+
+static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
+						 int input, u64 offset, u64 size)
+{
+	struct perf_session *session = container_of(header, struct perf_session, header);
+	struct {
+		struct perf_event_header   header;
+		u8			   build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
+		char			   filename[0];
+	} old_bev;
+	struct build_id_event bev;
+	char filename[PATH_MAX];
+	u64 limit = offset + size;
+
+	while (offset < limit) {
+		ssize_t len;
+
+		if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
+			return -1;
+
+		if (header->needs_swap)
+			perf_event_header__bswap(&old_bev.header);
+
+		len = old_bev.header.size - sizeof(old_bev);
+		if (read(input, filename, len) != len)
+			return -1;
+
+		bev.header = old_bev.header;
+
+		/*
+		 * As the pid is the missing value, we need to fill
+		 * it properly. The header.misc value give us nice hint.
+		 */
+		bev.pid	= HOST_KERNEL_ID;
+		if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
+		    bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
+			bev.pid	= DEFAULT_GUEST_KERNEL_ID;
+
+		memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
+		__event_process_build_id(&bev, filename, session);
+
+		offset += bev.header.size;
+	}
+
+	return 0;
+}
+
+static int perf_header__read_build_ids(struct perf_header *header,
+				       int input, u64 offset, u64 size)
+{
+	struct perf_session *session = container_of(header, struct perf_session, header);
+	struct build_id_event bev;
+	char filename[PATH_MAX];
+	u64 limit = offset + size, orig_offset = offset;
+	int err = -1;
+
+	while (offset < limit) {
+		ssize_t len;
+
+		if (read(input, &bev, sizeof(bev)) != sizeof(bev))
+			goto out;
+
+		if (header->needs_swap)
+			perf_event_header__bswap(&bev.header);
+
+		len = bev.header.size - sizeof(bev);
+		if (read(input, filename, len) != len)
+			goto out;
+		/*
+		 * The a1645ce1 changeset:
+		 *
+		 * "perf: 'perf kvm' tool for monitoring guest performance from host"
+		 *
+		 * Added a field to struct build_id_event that broke the file
+		 * format.
+		 *
+		 * Since the kernel build-id is the first entry, process the
+		 * table using the old format if the well known
+		 * '[kernel.kallsyms]' string for the kernel build-id has the
+		 * first 4 characters chopped off (where the pid_t sits).
+		 */
+		if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
+			if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
+				return -1;
+			return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
+		}
+
+		__event_process_build_id(&bev, filename, session);
+
+		offset += bev.header.size;
+	}
+	err = 0;
+out:
+	return err;
+}
+
+static int process_trace_info(struct perf_file_section *section __unused,
+			      struct perf_header *ph __unused,
+			      int feat __unused, int fd)
+{
+	trace_report(fd, false);
+	return 0;
+}
+
+static int process_build_id(struct perf_file_section *section,
+			    struct perf_header *ph,
+			    int feat __unused, int fd)
+{
+	if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
+		pr_debug("Failed to read buildids, continuing...\n");
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
 	void (*print)(struct perf_header *h, int fd, FILE *fp);
+	int (*process)(struct perf_file_section *section,
+		       struct perf_header *h, int feat, int fd);
 	const char *name;
 	bool full_only;
 };
 
 #define FEAT_OPA(n, func) \
 	[n] = { .name = #n, .write = write_##func, .print = print_##func }
+#define FEAT_OPP(n, func) \
+	[n] = { .name = #n, .write = write_##func, .print = print_##func, \
+		.process = process_##func }
 #define FEAT_OPF(n, func) \
-	[n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true }
+	[n] = { .name = #n, .write = write_##func, .print = print_##func, \
+		.full_only = true }
 
 /* feature_ops not implemented: */
 #define print_trace_info		NULL
 #define print_build_id			NULL
 
 static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
-	FEAT_OPA(HEADER_TRACE_INFO,	trace_info),
-	FEAT_OPA(HEADER_BUILD_ID,	build_id),
+	FEAT_OPP(HEADER_TRACE_INFO,	trace_info),
+	FEAT_OPP(HEADER_BUILD_ID,	build_id),
 	FEAT_OPA(HEADER_HOSTNAME,	hostname),
 	FEAT_OPA(HEADER_OSRELEASE,	osrelease),
 	FEAT_OPA(HEADER_VERSION,	version),
@@ -1336,6 +1607,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPA(HEADER_CMDLINE,	cmdline),
 	FEAT_OPF(HEADER_CPU_TOPOLOGY,	cpu_topology),
 	FEAT_OPF(HEADER_NUMA_TOPOLOGY,	numa_topology),
+	FEAT_OPA(HEADER_PMU_MAPPINGS,	pmu_mappings),
 };
 
 struct header_print_data {
@@ -1689,156 +1961,6 @@ int perf_file_header__read(struct perf_file_header *header,
 	return 0;
 }
 
-static int __event_process_build_id(struct build_id_event *bev,
-				    char *filename,
-				    struct perf_session *session)
-{
-	int err = -1;
-	struct list_head *head;
-	struct machine *machine;
-	u16 misc;
-	struct dso *dso;
-	enum dso_kernel_type dso_type;
-
-	machine = perf_session__findnew_machine(session, bev->pid);
-	if (!machine)
-		goto out;
-
-	misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-
-	switch (misc) {
-	case PERF_RECORD_MISC_KERNEL:
-		dso_type = DSO_TYPE_KERNEL;
-		head = &machine->kernel_dsos;
-		break;
-	case PERF_RECORD_MISC_GUEST_KERNEL:
-		dso_type = DSO_TYPE_GUEST_KERNEL;
-		head = &machine->kernel_dsos;
-		break;
-	case PERF_RECORD_MISC_USER:
-	case PERF_RECORD_MISC_GUEST_USER:
-		dso_type = DSO_TYPE_USER;
-		head = &machine->user_dsos;
-		break;
-	default:
-		goto out;
-	}
-
-	dso = __dsos__findnew(head, filename);
-	if (dso != NULL) {
-		char sbuild_id[BUILD_ID_SIZE * 2 + 1];
-
-		dso__set_build_id(dso, &bev->build_id);
-
-		if (filename[0] == '[')
-			dso->kernel = dso_type;
-
-		build_id__sprintf(dso->build_id, sizeof(dso->build_id),
-				  sbuild_id);
-		pr_debug("build id event received for %s: %s\n",
-			 dso->long_name, sbuild_id);
-	}
-
-	err = 0;
-out:
-	return err;
-}
-
-static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
-						 int input, u64 offset, u64 size)
-{
-	struct perf_session *session = container_of(header, struct perf_session, header);
-	struct {
-		struct perf_event_header   header;
-		u8			   build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
-		char			   filename[0];
-	} old_bev;
-	struct build_id_event bev;
-	char filename[PATH_MAX];
-	u64 limit = offset + size;
-
-	while (offset < limit) {
-		ssize_t len;
-
-		if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
-			return -1;
-
-		if (header->needs_swap)
-			perf_event_header__bswap(&old_bev.header);
-
-		len = old_bev.header.size - sizeof(old_bev);
-		if (read(input, filename, len) != len)
-			return -1;
-
-		bev.header = old_bev.header;
-
-		/*
-		 * As the pid is the missing value, we need to fill
-		 * it properly. The header.misc value give us nice hint.
-		 */
-		bev.pid	= HOST_KERNEL_ID;
-		if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
-		    bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
-			bev.pid	= DEFAULT_GUEST_KERNEL_ID;
-
-		memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
-		__event_process_build_id(&bev, filename, session);
-
-		offset += bev.header.size;
-	}
-
-	return 0;
-}
-
-static int perf_header__read_build_ids(struct perf_header *header,
-				       int input, u64 offset, u64 size)
-{
-	struct perf_session *session = container_of(header, struct perf_session, header);
-	struct build_id_event bev;
-	char filename[PATH_MAX];
-	u64 limit = offset + size, orig_offset = offset;
-	int err = -1;
-
-	while (offset < limit) {
-		ssize_t len;
-
-		if (read(input, &bev, sizeof(bev)) != sizeof(bev))
-			goto out;
-
-		if (header->needs_swap)
-			perf_event_header__bswap(&bev.header);
-
-		len = bev.header.size - sizeof(bev);
-		if (read(input, filename, len) != len)
-			goto out;
-		/*
-		 * The a1645ce1 changeset:
-		 *
-		 * "perf: 'perf kvm' tool for monitoring guest performance from host"
-		 *
-		 * Added a field to struct build_id_event that broke the file
-		 * format.
-		 *
-		 * Since the kernel build-id is the first entry, process the
-		 * table using the old format if the well known
-		 * '[kernel.kallsyms]' string for the kernel build-id has the
-		 * first 4 characters chopped off (where the pid_t sits).
-		 */
-		if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
-			if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
-				return -1;
-			return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
-		}
-
-		__event_process_build_id(&bev, filename, session);
-
-		offset += bev.header.size;
-	}
-	err = 0;
-out:
-	return err;
-}
-
 static int perf_file_section__process(struct perf_file_section *section,
 				      struct perf_header *ph,
 				      int feat, int fd, void *data __used)
@@ -1854,19 +1976,10 @@ static int perf_file_section__process(struct perf_file_section *section,
 		return 0;
 	}
 
-	switch (feat) {
-	case HEADER_TRACE_INFO:
-		trace_report(fd, false);
-		break;
-	case HEADER_BUILD_ID:
-		if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
-			pr_debug("Failed to read buildids, continuing...\n");
-		break;
-	default:
-		break;
-	}
+	if (!feat_ops[feat].process)
+		return 0;
 
-	return 0;
+	return feat_ops[feat].process(section, ph, feat, fd);
 }
 
 static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index ac4ec95..9b4d407 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -11,6 +11,7 @@
 
 enum {
 	HEADER_RESERVED		= 0,	/* always cleared */
+	HEADER_FIRST_FEATURE	= 1,
 	HEADER_TRACE_INFO	= 1,
 	HEADER_BUILD_ID,
 
@@ -26,6 +27,7 @@ enum {
 	HEADER_EVENT_DESC,
 	HEADER_CPU_TOPOLOGY,
 	HEADER_NUMA_TOPOLOGY,
+	HEADER_PMU_MAPPINGS,
 
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 62cdee7..f1584833 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -15,7 +15,7 @@
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
 
 /* same as for_each_set_bit() but use bit as value to start with */
-#define for_each_set_bit_cont(bit, addr, size) \
+#define for_each_set_bit_from(bit, addr, size) \
 	for ((bit) = find_next_bit((addr), (size), (bit));	\
 	     (bit) < (size);					\
 	     (bit) = find_next_bit((addr), (size), (bit) + 1))
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index b029296..4944b6d 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -687,7 +687,7 @@ parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
 }
 
 static enum event_result
-parse_raw_event(const char **strp, struct perf_event_attr *attr)
+parse_raw_config(const char **strp, struct perf_event_attr *attr)
 {
 	const char *str = *strp;
 	u64 config;
@@ -702,7 +702,6 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
 			return EVT_FAILED;
 
 		*strp = end;
-		attr->type = PERF_TYPE_RAW;
 		attr->config = config;
 		return EVT_HANDLED;
 	}
@@ -710,6 +709,83 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
 }
 
 static enum event_result
+parse_raw_event(const char **strp, struct perf_event_attr *attr)
+{
+	if (parse_raw_config(strp, attr) != EVT_HANDLED)
+		return EVT_FAILED;
+
+	attr->type = PERF_TYPE_RAW;
+	return EVT_HANDLED;
+}
+
+#define EVENT_SOURCE_DIR "/sys/bus/event_source/devices"
+
+static u64 read_sysfs_entry(const char *path)
+{
+	char buf[19];
+	int fd;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return -1;
+
+	if (read(fd, buf, sizeof(buf)) < 0) {
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return atoll(buf);
+}
+
+static u64 get_pmu_type(const char *pmu_name)
+{
+	char evt_path[MAXPATHLEN];
+
+	snprintf(evt_path, MAXPATHLEN, "%s/%s/type", EVENT_SOURCE_DIR,
+		 pmu_name);
+
+	return read_sysfs_entry(evt_path);
+}
+
+static u64 get_pmu_event_config(const char *pmu_name, const char *evt_name)
+{
+	char evt_path[MAXPATHLEN];
+
+	snprintf(evt_path, MAXPATHLEN, "%s/%s/events/%s", EVENT_SOURCE_DIR,
+		 pmu_name, evt_name);
+
+	return read_sysfs_entry(evt_path);
+}
+
+static enum event_result
+parse_sysfs_event(const char **strp, struct perf_event_attr *attr)
+{
+	char *pmu_name, *evt_name;
+	u64 type, config;
+
+	pmu_name = strchr(*strp, ':');
+	if (!pmu_name)
+		return EVT_FAILED;
+	pmu_name = strndup(*strp, pmu_name - *strp);
+	type = get_pmu_type(pmu_name);
+	if ((int)type < 0)
+		return EVT_FAILED;
+	attr->type = type;
+
+	evt_name = strchr(*strp, ':') + 1;
+	config = get_pmu_event_config(pmu_name, evt_name);
+	*strp += strlen(pmu_name) + 1; /* + 1 for the ':' */
+
+	if ((int)config < 0)
+		return parse_raw_config(strp, attr);
+
+	attr->config = config;
+	*strp += strlen(evt_name);
+	return EVT_HANDLED;
+}
+
+static enum event_result
 parse_numeric_event(const char **strp, struct perf_event_attr *attr)
 {
 	const char *str = *strp;
@@ -800,6 +876,10 @@ parse_event_symbols(struct perf_evlist *evlist, const char **str,
 {
 	enum event_result ret;
 
+	ret = parse_sysfs_event(str, attr);
+	if (ret != EVT_FAILED)
+		goto modifier;
+
 	ret = parse_tracepoint_event(evlist, str, attr);
 	if (ret != EVT_FAILED)
 		goto modifier;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900..f6f5794 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,6 +47,7 @@
 #include "trace-event.h"	/* For __unused */
 #include "probe-event.h"
 #include "probe-finder.h"
+#include "session.h"
 
 #define MAX_CMDLEN 256
 #define MAX_PROBE_ARGS 128
@@ -73,6 +74,8 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
 }
 
 static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
+static int convert_name_to_addr(struct perf_probe_event *pev,
+				const char *exec);
 static struct machine machine;
 
 /* Initialize symbol maps and path of vmlinux/modules */
@@ -173,6 +176,31 @@ const char *kernel_get_module_path(const char *module)
 	return (dso) ? dso->long_name : NULL;
 }
 
+static int init_user_exec(void)
+{
+	int ret = 0;
+
+	symbol_conf.try_vmlinux_path = false;
+	symbol_conf.sort_by_name = true;
+	ret = symbol__init();
+	if (ret < 0)
+		pr_debug("Failed to init symbol map.\n");
+
+	return ret;
+}
+
+static int convert_to_perf_probe_point(struct probe_trace_point *tp,
+					struct perf_probe_point *pp)
+{
+	pp->function = strdup(tp->symbol);
+	if (pp->function == NULL)
+		return -ENOMEM;
+	pp->offset = tp->offset;
+	pp->retprobe = tp->retprobe;
+
+	return 0;
+}
+
 #ifdef DWARF_SUPPORT
 /* Open new debuginfo of given module */
 static struct debuginfo *open_debuginfo(const char *module)
@@ -227,10 +255,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 	if (ret <= 0) {
 		pr_debug("Failed to find corresponding probes from "
 			 "debuginfo. Use kprobe event information.\n");
-		pp->function = strdup(tp->symbol);
-		if (pp->function == NULL)
-			return -ENOMEM;
-		pp->offset = tp->offset;
+		return convert_to_perf_probe_point(tp, pp);
 	}
 	pp->retprobe = tp->retprobe;
 
@@ -275,12 +300,22 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
 /* Try to find perf_probe_event with debuginfo */
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 					  struct probe_trace_event **tevs,
-					  int max_tevs, const char *module)
+					  int max_tevs, const char *target)
 {
 	bool need_dwarf = perf_probe_event_need_dwarf(pev);
-	struct debuginfo *dinfo = open_debuginfo(module);
+	struct debuginfo *dinfo;
 	int ntevs, ret = 0;
 
+	if (pev->uprobes) {
+		if (need_dwarf) {
+			pr_warning("Debuginfo-analysis is not yet supported"
+					" with -x/--exec option.\n");
+			return -ENOSYS;
+		}
+		return convert_name_to_addr(pev, target);
+	}
+
+	dinfo = open_debuginfo(target);
 	if (!dinfo) {
 		if (need_dwarf) {
 			pr_warning("Failed to open debuginfo file.\n");
@@ -297,9 +332,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 
 	if (ntevs > 0) {	/* Succeeded to find trace events */
 		pr_debug("find %d probe_trace_events.\n", ntevs);
-		if (module)
+		if (target)
 			ret = add_module_to_probe_trace_events(*tevs, ntevs,
-							       module);
+							       target);
 		return ret < 0 ? ret : ntevs;
 	}
 
@@ -606,23 +641,20 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
 		pr_err("Failed to find symbol %s in kernel.\n", tp->symbol);
 		return -ENOENT;
 	}
-	pp->function = strdup(tp->symbol);
-	if (pp->function == NULL)
-		return -ENOMEM;
-	pp->offset = tp->offset;
-	pp->retprobe = tp->retprobe;
-
-	return 0;
+	return convert_to_perf_probe_point(tp, pp);
 }
 
 static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
 				struct probe_trace_event **tevs __unused,
-				int max_tevs __unused, const char *mod __unused)
+				int max_tevs __unused, const char *target)
 {
 	if (perf_probe_event_need_dwarf(pev)) {
 		pr_warning("Debuginfo-analysis is not supported.\n");
 		return -ENOSYS;
 	}
+	if (pev->uprobes)
+		return convert_name_to_addr(pev, target);
+
 	return 0;
 }
 
@@ -887,6 +919,11 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 		return -EINVAL;
 	}
 
+	if (pev->uprobes && !pp->function) {
+		semantic_error("No function specified for uprobes");
+		return -EINVAL;
+	}
+
 	if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
 		semantic_error("Offset/Line/Lazy pattern can't be used with "
 			       "return probe.\n");
@@ -896,6 +933,11 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
 		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
 		 pp->lazy_line);
+
+	if (pev->uprobes && perf_probe_event_need_dwarf(pev)) {
+		semantic_error("no dwarf based probes for uprobes.");
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -1344,11 +1386,18 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 	if (buf == NULL)
 		return NULL;
 
-	len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
-			 tp->retprobe ? 'r' : 'p',
-			 tev->group, tev->event,
-			 tp->module ?: "", tp->module ? ":" : "",
-			 tp->symbol, tp->offset);
+	if (tev->uprobes)
+		len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s:%s",
+				 tp->retprobe ? 'r' : 'p',
+				 tev->group, tev->event,
+				 tp->module, tp->symbol);
+	else
+		len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
+				 tp->retprobe ? 'r' : 'p',
+				 tev->group, tev->event,
+				 tp->module ?: "", tp->module ? ":" : "",
+				 tp->symbol, tp->offset);
+
 	if (len <= 0)
 		goto error;
 
@@ -1367,7 +1416,7 @@ error:
 }
 
 static int convert_to_perf_probe_event(struct probe_trace_event *tev,
-				       struct perf_probe_event *pev)
+			       struct perf_probe_event *pev, bool is_kprobe)
 {
 	char buf[64] = "";
 	int i, ret;
@@ -1379,7 +1428,11 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
 		return -ENOMEM;
 
 	/* Convert trace_point to probe_point */
-	ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
+	if (is_kprobe)
+		ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point);
+	else
+		ret = convert_to_perf_probe_point(&tev->point, &pev->point);
+
 	if (ret < 0)
 		return ret;
 
@@ -1475,7 +1528,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
 	memset(tev, 0, sizeof(*tev));
 }
 
-static int open_kprobe_events(bool readwrite)
+static int open_probe_events(const char *trace_file, bool readwrite)
 {
 	char buf[PATH_MAX];
 	const char *__debugfs;
@@ -1487,7 +1540,7 @@ static int open_kprobe_events(bool readwrite)
 		return -ENOENT;
 	}
 
-	ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs);
+	ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
 	if (ret >= 0) {
 		pr_debug("Opening %s write=%d\n", buf, readwrite);
 		if (readwrite && !probe_event_dry_run)
@@ -1495,19 +1548,42 @@ static int open_kprobe_events(bool readwrite)
 		else
 			ret = open(buf, O_RDONLY, 0);
 	}
+	return ret;
+}
+
+static void print_warn_msg(const char *file, const char *config)
+{
+	if (errno == ENOENT)
+		pr_warning("%s file does not exist - please rebuild kernel"
+				" with %s.\n", file, config);
+	else
+		pr_warning("Failed to open %s file: %s\n", file,
+				strerror(errno));
+}
+
+static int open_kprobe_events(bool readwrite)
+{
+	int ret;
+
+	ret = open_probe_events("tracing/kprobe_events", readwrite);
+	if (ret < 0)
+		print_warn_msg("kprobe_events", "CONFIG_KPROBE_EVENTS");
 
-	if (ret < 0) {
-		if (errno == ENOENT)
-			pr_warning("kprobe_events file does not exist - please"
-				 " rebuild kernel with CONFIG_KPROBE_EVENT.\n");
-		else
-			pr_warning("Failed to open kprobe_events file: %s\n",
-				   strerror(errno));
-	}
 	return ret;
 }
 
-/* Get raw string list of current kprobe_events */
+static int open_uprobe_events(bool readwrite)
+{
+	int ret;
+
+	ret = open_probe_events("tracing/uprobe_events", readwrite);
+	if (ret < 0)
+		print_warn_msg("uprobe_events", "CONFIG_UPROBE_EVENTS");
+
+	return ret;
+}
+
+/* Get raw string list of current kprobe_events  or uprobe_events */
 static struct strlist *get_probe_trace_command_rawlist(int fd)
 {
 	int ret, idx;
@@ -1572,36 +1648,26 @@ static int show_perf_probe_event(struct perf_probe_event *pev)
 	return ret;
 }
 
-/* List up current perf-probe events */
-int show_perf_probe_events(void)
+static int __show_perf_probe_events(int fd, bool is_kprobe)
 {
-	int fd, ret;
+	int ret = 0;
 	struct probe_trace_event tev;
 	struct perf_probe_event pev;
 	struct strlist *rawlist;
 	struct str_node *ent;
 
-	setup_pager();
-	ret = init_vmlinux();
-	if (ret < 0)
-		return ret;
-
 	memset(&tev, 0, sizeof(tev));
 	memset(&pev, 0, sizeof(pev));
 
-	fd = open_kprobe_events(false);
-	if (fd < 0)
-		return fd;
-
 	rawlist = get_probe_trace_command_rawlist(fd);
-	close(fd);
 	if (!rawlist)
 		return -ENOENT;
 
 	strlist__for_each(ent, rawlist) {
 		ret = parse_probe_trace_command(ent->s, &tev);
 		if (ret >= 0) {
-			ret = convert_to_perf_probe_event(&tev, &pev);
+			ret = convert_to_perf_probe_event(&tev, &pev,
+								is_kprobe);
 			if (ret >= 0)
 				ret = show_perf_probe_event(&pev);
 		}
@@ -1611,6 +1677,31 @@ int show_perf_probe_events(void)
 			break;
 	}
 	strlist__delete(rawlist);
+	return ret;
+}
+
+/* List up current perf-probe events */
+int show_perf_probe_events(void)
+{
+	int fd, ret;
+
+	setup_pager();
+	fd = open_kprobe_events(false);
+	if (fd < 0)
+		return fd;
+
+	ret = init_vmlinux();
+	if (ret < 0)
+		return ret;
+
+	ret = __show_perf_probe_events(fd, true);
+	close(fd);
+
+	fd = open_uprobe_events(false);
+	if (fd >= 0) {
+		ret = __show_perf_probe_events(fd, false);
+		close(fd);
+	}
 
 	return ret;
 }
@@ -1720,7 +1811,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 	const char *event, *group;
 	struct strlist *namelist;
 
-	fd = open_kprobe_events(true);
+	if (pev->uprobes)
+		fd = open_uprobe_events(true);
+	else
+		fd = open_kprobe_events(true);
 	if (fd < 0)
 		return fd;
 	/* Get current event names */
@@ -1798,14 +1892,14 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
 
 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 					  struct probe_trace_event **tevs,
-					  int max_tevs, const char *module)
+					  int max_tevs, const char *target)
 {
 	struct symbol *sym;
 	int ret = 0, i;
 	struct probe_trace_event *tev;
 
 	/* Convert perf_probe_event with debuginfo */
-	ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
+	ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
 	if (ret != 0)
 		return ret;	/* Found in debuginfo or got an error */
 
@@ -1821,8 +1915,8 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		goto error;
 	}
 
-	if (module) {
-		tev->point.module = strdup(module);
+	if (target) {
+		tev->point.module = strdup(target);
 		if (tev->point.module == NULL) {
 			ret = -ENOMEM;
 			goto error;
@@ -1832,6 +1926,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 	tev->point.offset = pev->point.offset;
 	tev->point.retprobe = pev->point.retprobe;
 	tev->nargs = pev->nargs;
+	tev->uprobes = pev->uprobes;
 	if (tev->nargs) {
 		tev->args = zalloc(sizeof(struct probe_trace_arg)
 				   * tev->nargs);
@@ -1862,6 +1957,9 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
+	if (pev->uprobes)
+		return 1;
+
 	/* Currently just checking function name from symbol map */
 	sym = __find_kernel_function_by_name(tev->point.symbol, NULL);
 	if (!sym) {
@@ -1886,17 +1984,21 @@ struct __event_package {
 };
 
 int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
-			  int max_tevs, const char *module, bool force_add)
+			  int max_tevs, const char *target, bool force_add)
 {
-	int i, j, ret;
+	int i, j, ret = 0;
 	struct __event_package *pkgs;
 
 	pkgs = zalloc(sizeof(struct __event_package) * npevs);
 	if (pkgs == NULL)
 		return -ENOMEM;
 
-	/* Init vmlinux path */
-	ret = init_vmlinux();
+	if (!pevs->uprobes)
+		/* Init vmlinux path */
+		ret = init_vmlinux();
+	else
+		ret = init_user_exec();
+
 	if (ret < 0) {
 		free(pkgs);
 		return ret;
@@ -1909,7 +2011,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 		ret  = convert_to_probe_trace_events(pkgs[i].pev,
 						     &pkgs[i].tevs,
 						     max_tevs,
-						     module);
+						     target);
 		if (ret < 0)
 			goto end;
 		pkgs[i].ntevs = ret;
@@ -1968,23 +2070,15 @@ error:
 	return ret;
 }
 
-static int del_trace_probe_event(int fd, const char *group,
-				  const char *event, struct strlist *namelist)
+static int del_trace_probe_event(int fd, const char *buf,
+						  struct strlist *namelist)
 {
-	char buf[128];
 	struct str_node *ent, *n;
-	int found = 0, ret = 0;
-
-	ret = e_snprintf(buf, 128, "%s:%s", group, event);
-	if (ret < 0) {
-		pr_err("Failed to copy event.\n");
-		return ret;
-	}
+	int ret = -1;
 
 	if (strpbrk(buf, "*?")) { /* Glob-exp */
 		strlist__for_each_safe(ent, n, namelist)
 			if (strglobmatch(ent->s, buf)) {
-				found++;
 				ret = __del_trace_probe_event(fd, ent);
 				if (ret < 0)
 					break;
@@ -1993,40 +2087,41 @@ static int del_trace_probe_event(int fd, const char *group,
 	} else {
 		ent = strlist__find(namelist, buf);
 		if (ent) {
-			found++;
 			ret = __del_trace_probe_event(fd, ent);
 			if (ret >= 0)
 				strlist__remove(namelist, ent);
 		}
 	}
-	if (found == 0 && ret >= 0)
-		pr_info("Info: Event \"%s\" does not exist.\n", buf);
-
 	return ret;
 }
 
 int del_perf_probe_events(struct strlist *dellist)
 {
-	int fd, ret = 0;
+	int ret = -1, ufd = -1, kfd = -1;
+	char buf[128];
 	const char *group, *event;
 	char *p, *str;
 	struct str_node *ent;
-	struct strlist *namelist;
-
-	fd = open_kprobe_events(true);
-	if (fd < 0)
-		return fd;
+	struct strlist *namelist = NULL, *unamelist = NULL;
 
 	/* Get current event names */
-	namelist = get_probe_trace_event_names(fd, true);
-	if (namelist == NULL)
-		return -EINVAL;
+	kfd = open_kprobe_events(true);
+	if (kfd < 0)
+		return kfd;
+	namelist = get_probe_trace_event_names(kfd, true);
+
+	ufd = open_uprobe_events(true);
+	if (ufd >= 0)
+		unamelist = get_probe_trace_event_names(ufd, true);
+
+	if (namelist == NULL && unamelist == NULL)
+		goto error;
 
 	strlist__for_each(ent, dellist) {
 		str = strdup(ent->s);
 		if (str == NULL) {
 			ret = -ENOMEM;
-			break;
+			goto error;
 		}
 		pr_debug("Parsing: %s\n", str);
 		p = strchr(str, ':');
@@ -2038,17 +2133,40 @@ int del_perf_probe_events(struct strlist *dellist)
 			group = "*";
 			event = str;
 		}
+
+		ret = e_snprintf(buf, 128, "%s:%s", group, event);
+		if (ret < 0) {
+			pr_err("Failed to copy event.");
+			free(str);
+			goto error;
+		}
+
 		pr_debug("Group: %s, Event: %s\n", group, event);
-		ret = del_trace_probe_event(fd, group, event, namelist);
+		if (namelist)
+			ret = del_trace_probe_event(kfd, buf, namelist);
+		if (unamelist && ret != 0)
+			ret = del_trace_probe_event(ufd, buf, unamelist);
+
 		free(str);
-		if (ret < 0)
-			break;
+		if (ret != 0)
+			pr_info("Info: Event \"%s\" does not exist.\n", buf);
 	}
-	strlist__delete(namelist);
-	close(fd);
 
+error:
+	if (kfd >= 0) {
+		if (namelist)
+			strlist__delete(namelist);
+		close(kfd);
+	}
+
+	if (ufd >= 0) {
+		if (unamelist)
+			strlist__delete(unamelist);
+		close(ufd);
+	}
 	return ret;
 }
+
 /* TODO: don't use a global variable for filter ... */
 static struct strfilter *available_func_filter;
 
@@ -2065,13 +2183,24 @@ static int filter_available_functions(struct map *map __unused,
 	return 1;
 }
 
-int show_available_funcs(const char *module, struct strfilter *_filter)
+static int __show_available_funcs(struct map *map)
+{
+	if (map__load(map, filter_available_functions)) {
+		pr_err("Failed to load map.\n");
+		return -EINVAL;
+	}
+	if (!dso__sorted_by_name(map->dso, map->type))
+		dso__sort_by_name(map->dso, map->type);
+
+	dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
+	return 0;
+}
+
+static int available_kernel_funcs(const char *module)
 {
 	struct map *map;
 	int ret;
 
-	setup_pager();
-
 	ret = init_vmlinux();
 	if (ret < 0)
 		return ret;
@@ -2081,14 +2210,123 @@ int show_available_funcs(const char *module, struct strfilter *_filter)
 		pr_err("Failed to find %s map.\n", (module) ? : "kernel");
 		return -EINVAL;
 	}
+	return __show_available_funcs(map);
+}
+
+static int available_user_funcs(const char *target)
+{
+	struct map *map;
+	int ret;
+
+	ret = init_user_exec();
+	if (ret < 0)
+		return ret;
+
+	map = dso__new_map(target);
+	ret = __show_available_funcs(map);
+	dso__delete(map->dso);
+	map__delete(map);
+	return ret;
+}
+
+int show_available_funcs(const char *target, struct strfilter *_filter,
+					bool user)
+{
+	setup_pager();
 	available_func_filter = _filter;
+
+	if (!user)
+		return available_kernel_funcs(target);
+
+	return available_user_funcs(target);
+}
+
+/*
+ * uprobe_events only accepts address:
+ * Convert function and any offset to address
+ */
+static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
+{
+	struct perf_probe_point *pp = &pev->point;
+	struct symbol *sym;
+	struct map *map = NULL;
+	char *function = NULL, *name = NULL;
+	int ret = -EINVAL;
+	unsigned long long vaddr = 0;
+
+	if (!pp->function)
+		goto out;
+
+	function = strdup(pp->function);
+	if (!function) {
+		pr_warning("Failed to allocate memory by strdup.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	name = realpath(exec, NULL);
+	if (!name) {
+		pr_warning("Cannot find realpath for %s.\n", exec);
+		goto out;
+	}
+	map = dso__new_map(name);
+	if (!map) {
+		pr_warning("Cannot find appropriate DSO for %s.\n", exec);
+		goto out;
+	}
+	available_func_filter = strfilter__new(function, NULL);
 	if (map__load(map, filter_available_functions)) {
 		pr_err("Failed to load map.\n");
 		return -EINVAL;
 	}
-	if (!dso__sorted_by_name(map->dso, map->type))
-		dso__sort_by_name(map->dso, map->type);
 
-	dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
-	return 0;
+	sym = map__find_symbol_by_name(map, function, NULL);
+	if (!sym) {
+		pr_warning("Cannot find %s in DSO %s\n", function, exec);
+		goto out;
+	}
+
+	if (map->start > sym->start)
+		vaddr = map->start;
+	vaddr += sym->start + pp->offset + map->pgoff;
+	pp->offset = 0;
+
+	if (!pev->event) {
+		pev->event = function;
+		function = NULL;
+	}
+	if (!pev->group) {
+		char *ptr1, *ptr2;
+
+		pev->group = zalloc(sizeof(char *) * 64);
+		ptr1 = strdup(basename(exec));
+		if (ptr1) {
+			ptr2 = strpbrk(ptr1, "-._");
+			if (ptr2)
+				*ptr2 = '\0';
+			e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP,
+					ptr1);
+			free(ptr1);
+		}
+	}
+	free(pp->function);
+	pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS);
+	if (!pp->function) {
+		ret = -ENOMEM;
+		pr_warning("Failed to allocate memory by zalloc.\n");
+		goto out;
+	}
+	e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr);
+	ret = 0;
+
+out:
+	if (map) {
+		dso__delete(map->dso);
+		map__delete(map);
+	}
+	if (function)
+		free(function);
+	if (name)
+		free(name);
+	return ret;
 }
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index a7dee83..f9f3de8 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -7,7 +7,7 @@
 
 extern bool probe_event_dry_run;
 
-/* kprobe-tracer tracing point */
+/* kprobe-tracer and uprobe-tracer tracing point */
 struct probe_trace_point {
 	char		*symbol;	/* Base symbol */
 	char		*module;	/* Module name */
@@ -21,7 +21,7 @@ struct probe_trace_arg_ref {
 	long				offset;	/* Offset value */
 };
 
-/* kprobe-tracer tracing argument */
+/* kprobe-tracer and uprobe-tracer tracing argument */
 struct probe_trace_arg {
 	char				*name;	/* Argument name */
 	char				*value;	/* Base value */
@@ -29,12 +29,13 @@ struct probe_trace_arg {
 	struct probe_trace_arg_ref	*ref;	/* Referencing offset */
 };
 
-/* kprobe-tracer tracing event (point + arg) */
+/* kprobe-tracer and uprobe-tracer tracing event (point + arg) */
 struct probe_trace_event {
 	char				*event;	/* Event name */
 	char				*group;	/* Group name */
 	struct probe_trace_point	point;	/* Trace point */
 	int				nargs;	/* Number of args */
+	bool				uprobes;	/* uprobes only */
 	struct probe_trace_arg		*args;	/* Arguments */
 };
 
@@ -70,6 +71,7 @@ struct perf_probe_event {
 	char			*group;	/* Group name */
 	struct perf_probe_point	point;	/* Probe point */
 	int			nargs;	/* Number of arguments */
+	bool			uprobes;
 	struct perf_probe_arg	*args;	/* Arguments */
 };
 
@@ -129,8 +131,8 @@ extern int show_line_range(struct line_range *lr, const char *module);
 extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
 			       int max_probe_points, const char *module,
 			       struct strfilter *filter, bool externs);
-extern int show_available_funcs(const char *module, struct strfilter *filter);
-
+extern int show_available_funcs(const char *module, struct strfilter *filter,
+				bool user);
 
 /* Maximum index number of event-name postfix */
 #define MAX_EVENT_INDEX	1024
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 215d50f..d19cda0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2762,3 +2762,11 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
 
 	return ret;
 }
+
+struct map *dso__new_map(const char *name)
+{
+	struct dso *dso = dso__new(name);
+	struct map *map = map__new2(0, dso, MAP__FUNCTION);
+
+	return map;
+}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 123c2e1..2627a11 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -218,6 +218,7 @@ void dso__set_long_name(struct dso *dso, char *name);
 void dso__set_build_id(struct dso *dso, void *build_id);
 void dso__read_running_kernel_build_id(struct dso *dso,
 				       struct machine *machine);
+struct map *dso__new_map(const char *name);
 struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
 				u64 addr);
 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
